Using multiple threads with IntCurvesFace_ShapeIntersector in OCCT7.7.2

For example, I have 10 TopoDS_Faces and 100 Geom_Curve, and I need to calculate the intersection of each face and each line, 10*100=1000 times, which will take a lot of time. So I expect multiple threads to compute the intersection of each surface and curve in parallel. However, the actual calculation time was found to be slower. Why and how to solve it. Thank you very much.

This is the main part of my code:
std::vector Inter(const TopoDS_Face& face)
{
auto start = std::chrono::high_resolution_clock::now();

std::vector pnts{};
std::vector curves{};
IntCurveFace_ShapeIntersector intersector;
intersector.load(face, Precision::Confusion());

for(size_t i = 0 ;i {
Handle(GeomAdaptor_Curve) h_curve = new GeomAdaptor_Curve(curve[i]);
intersector.Perform(h_curve, h_curve->FirstParamter(), h_curve->LastParamter());
if(intersector.IsDone)
{
//push back points
}
}

auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration duration = end - start;
cout return pnts;
};

auto start = std::chrono::high_resolution_clock::now();

std::vector faces{};
std::vector<:vector>> res{};
for(size_t i = 0 ;i {
res.emplace_back(Inter(faces[i]));
}

auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration duration = end - start;
cout

gkv311 n's picture

So where is the actual multithreading logic in your code? What are the actual times?

Please also use Markdown or HTML syntax while posting the code on the forum, and consider fixing misprints ...

Bob Peng's picture

This is a function of the intersection of TopoDS_Face and each curve.

std::vector<gp_Pnt2d> Inter(const TopoDS_Face& face)
{
    auto start = std::chrono::high_resolution_clock::now();

    std::vector<gp_Pnt2d> pnts{};
    std::vector<Geom_Curve> curves{};
    IntCurveFace_ShapeIntersector intersector;
    intersector.load(face, Precision::Confusion());

    for(size_t i = 0 ;i < curves.size();++i)
    {
        Handle(GeomAdaptor_Curve) h_curve = new GeomAdaptor_Curve(curve[i]);
        intersector.Perform(h_curve, h_curve->FirstParamter(), h_curve->LastParamter());
        if(intersector.IsDone)
        {
            //push back points
        }
    }

    auto end = std::chrono::high_resolution_clock::now();
    std::chrono::duration<double> duration = end - start;
    cout << "Single Face:" << duration.count() ;
    return pnts;
};

This is the code for a single-threaded for loop.

auto start = std::chrono::high_resolution_clock::now();

std::vector<TopoDS_Face> faces{};
std::vector<std::vector<gp_Pnt2d>> res{};
for(size_t i = 0 ;i < faces.size();++i)
{
    res.emplace_back(Inter(faces[i]));
}

auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> duration = end - start;
cout << "Total:" << duration.count() ;

This is multi-threaded code.

std::vector<std::vector<gp_Pnt2d>> Inter_Batch(const std::vector<TopoDS_Face>& faces, size_t sta_idx. size_t end_idx)
{
    std::vector<std::vector<gp_Pnt2d>> pnts_vec{};
    for(size_t i = sta_idx; i < end_idx ; ++i)
    {
        std::vector<gp_Pnt2d> pnts = Inter(faces[i]);
        pnts_vec.emplace_back(pnts);
    }
    return pnts_vec;
}

auto start = std::chrono::high_resolution_clock::now();

std::vector<TopoDS_Face> faces{};
std::vector<std::vector<gp_Pnt2d>> res{};

unsigned int thread_no = std::min(static_cast<unsigned int>(faces.size()), std::thread::hardware_concurrency());
size_t batch_size = faces.size() / thread_no;
std::vector<std::future<std::vector<std::vector<gp_Pnt2d>>>> future{};
for(unsigned int i = 0; i < faces.size(); ++i)
{
    size_t sta_idx = i * batch_size;
    size_t end_idx = (i + 1 == thread_no) ? faces.size() : (i + 1) * batch_size;
    future.emplace_back(std::async(std::launch::async, Inter_Batch, std::ref(faces), sta_idx, end_idx));
}

for(size_t i = 0 ; i< future.size();++i)
{
    std::vector<std::vector<gp_Pnt2d>> pnts_vec = future[i].get();
    res.insert(res.end(), pnts_vec.begin(), pnts_vec.end());
}

auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> duration = end - start;
cout << "Total:" << duration.count() ;

In actual calculation, there are a total of 10 surfaces and 370 curves. The single-threaded loop takes between 1 and 3 seconds per face in debug mode, with an average of 2 seconds, for a total of 21 seconds. With multiple threads, each face ranges from two 2 to 15 seconds, for a total of 30 seconds.