DiscussionsIssue archiveOCCT:Foundation Classes

Archived issue #0032851

OCCT algorithms create/destroy a large number of threads when Intel TBB enabled

CommunityOCCT:Foundation Classesnew5 public notes

Search issues

Description

I've been using OCCT as a library to validate CAD geometries. I want to manage parallelism myself as I'm doing a lot of small operations with the pave filler and associated BOPs. When running my program under GDB I noticed a lot of threads being created, e.g. lines like:

  [New Thread 0x7fffee5b7640 (LWP 17248)]
  [New Thread 0x7fffed5b3640 (LWP 17249)]
  [New Thread 0x7fffec871640 (LWP 17250)]
  [New Thread 0x7fffed1b2640 (LWP 17252)]
  [New Thread 0x7fffed9b4640 (LWP 17253)]
  [New Thread 0x7fffef25f640 (LWP 17251)]
  [New Thread 0x7fffee1b6640 (LWP 17254)]
  [Thread 0x7fffee1b6640 (LWP 17254) exited]
  [Thread 0x7fffed9b4640 (LWP 17253) exited]
  [Thread 0x7fffef25f640 (LWP 17251) exited]
  [Thread 0x7fffec871640 (LWP 17250) exited]
  [Thread 0x7fffed5b3640 (LWP 17249) exited]
  [Thread 0x7fffee5b7640 (LWP 17248) exited]
  [Thread 0x7fffed1b2640 (LWP 17252) exited]

being printed out, every time BOPAlgo_PaveFiller is performed.

Steps to reproduce

Run with a version of OCCT compiled with Intel TBB enabled, e.g. OCCT as included in Ubuntu 21.10 is compiled like this. Then run:

  BOPAlgo_PaveFiller filler;
  filler.SetRunParallel(false);
  filler.SetArguments(shape_args);
  filler.Perform();

I can work around this issue by forcing the use of OCCT's built in thread pool, by calling:

  OSD_Parallel::SetUseOcctThreads(false)

during program initialization, but this feels like a bug.

The following looks like a useful part of the stack trace:

#0000007 0x00007ffff7e5c1fc in void tbb::parallel_for_each<OSD_Parallel::UniversalIterator, OSD_Parallel::FunctorInterface>(OSD_Parallel::UniversalIterator, OSD_Parallel::UniversalIterator, OSD_Parallel::FunctorInterface const&) () from /lib/x86_64-linux-gnu/libTKernel.so.7
#0000008 0x00007ffff7e5b7f3 in OSD_Parallel::forEachExternal(OSD_Parallel::UniversalIterator&, OSD_Parallel::UniversalIterator&, OSD_Parallel::FunctorInterface const&, int) () from /lib/x86_64-linux-gnu/libTKernel.so.7
#0000009 0x00007ffff585c4e1 in void OSD_Parallel::For<GeomLib_CheckCurveOnSurface_Local>(int, int, GeomLib_CheckCurveOnSurface_Local const&, bool) () from /lib/x86_64-linux-gnu/libTKGeomBase.so.7
#10 0x00007ffff585a15c in GeomLib_CheckCurveOnSurface::Perform(opencascade::handle<Geom2d_Curve> const&, bool) () from /lib/x86_64-linux-gnu/libTKGeomBase.so.7
#0000011 0x00007ffff7c4e10d in IntTools_Tools::ComputeTolerance(opencascade::handle<Geom_Curve> const&, opencascade::handle<Geom2d_Curve> const&, opencascade::handle<Geom_Surface> const&, double, double, double&, double&, double) () from /lib/x86_64-linux-gnu/libTKBO.so.7
#12 0x00007ffff7c35aaa in IntTools_FaceFace::ComputeTolReached3d() ()
   from /lib/x86_64-linux-gnu/libTKBO.so.7
#0000013 0x00007ffff7c3e576 in IntTools_FaceFace::Perform(TopoDS_Face const&, TopoDS_Face const&) ()
   from /lib/x86_64-linux-gnu/libTKBO.so.7
#0000014 0x00007ffff7d0ff02 in BOPAlgo_FaceFace::Perform() () from /lib/x86_64-linux-gnu/libTKBO.so.7
#0000015 0x00007ffff7d10227 in void OSD_Parallel::For<BOPTools_Parallel::Functor<NCollection_Vector<BOPAlgo_FaceFace> > >(int, int, BOPTools_Parallel::Functor<NCollection_Vector<BOPAlgo_FaceFace> > const&, bool) ()
   from /lib/x86_64-linux-gnu/libTKBO.so.7
#0000016 0x00007ffff7d002b2 in BOPAlgo_PaveFiller::PerformFF() () from /lib/x86_64-linux-gnu/libTKBO.so.7
#0000017 0x00007ffff7cdd25f in BOPAlgo_PaveFiller::PerformInternal() () from /lib/x86_64-linux-gnu/libTKBO.so.7
#0000018 0x00007ffff7cddc6c in BOPAlgo_PaveFiller::Perform() () from /lib/x86_64-linux-gnu/libTKBO.so.7

Public activity

5 archived notes

Participants are labeled by their role within this record.

01Commenter 3
The only thing I could imagine to alter TBB behavior is
> tbb::task_scheduler_init aScheduler (aNbThreads);

within src/OSD/OSD_Parallel_TBB.cxx.

If commenting these lines doesn't change behavior - than this threads spawning is by TBB design.
02Author
I noticed after posting that I should have written that I have to use:

     OSD_Parallel::SetUseOcctThreads(true);

(but can't see how to edit the issue)

Commenter 4, yes that call to task_scheduler_init() looked suspicious to me, i.e. is it causing thread pool to be reinitialized every time.

This Ubuntu box isn't my main dev machine (i.e. I don't normally have TBB headers installed) so haven't tried changing that line.
03Commenter 3
Commenter 5, fill free to share your updates when you'll have a time.
04Author
Sorry for the delay, it's been a bit of a struggle to reproduce because some defaults seem to have changed and it took a bit to track down what it was. I don't think I'll be affected by this bug in more recent versions of OCCT, as I explicitly disable parallel mode in the pave filler. The version currently bundled with Ubuntu (i.e. 7.5.1) apparently spawns/kills these threads independently of the parallel mode setting.

That said, for users that choose to turn it on I can confirm that removing that line causes a multitude of thread spawns/joins to stop so still seems like something that's worth fixing. I'll let you decide on what that fix is!

I'm including some cut-down C++ code, and a brep file that triggers this for me. I don't think the file is particularly special though, it's mostly default output of paramak (https://github.com/fusion-energy/paramak).
Attachment 2 (CPP) (1,247 bytes)   
Attachment 1 (BREP) (158,951 bytes)   
05Author
oops, forgot to note I'm testing with [revision removed] which still appears to be HEAD of the master branch

am happy to try with something else now I've figured out what's going on

Related records