Work with Multi-Threading

Vadim Asandiy

May 26, 2023

For multi-threaded loading and regeneration, BimNv SDK uses the Intel® oneAPI Threading Building Blocks (oneTBB) library.

Multi-Threaded Loading

By default, the thread count is obtained from the ODA thread pool. But if you need to set the thread count while loading files in multi-thread mode, override the method virtual int numThreads(OdDb::MultiThreadedMode mtMode) from OdDbBaseHostAppServices. For example:

//…
class MyServices : public OdNwHostAppServices
{
  //…  
  //method for setting thread count
  void setNumThreads(int numThreads)
  {
    m_numThreads = numThreads;
  }

  // override method for getting thread count
  int numThreads(OdDb::MultiThreadedMode mtMode) override
  {
    int numThrs = 1;
    bool bEnabled = false;
    switch (mtMode)
    {
      case OdDb::kMTLoading:
      bEnabled = GETBIT(getMtMode(), 1);
      break;
    }
    if (bEnabled)
      numThrs = m_numThreads;
      return numThrs;
  }

  protected:
    int m_numThreads;
};
//…

To open a file in multi-thread mode, use following code:

//…
OdNwHostAppServices* pHostApp;
OdString nwFile;
//…
OdInt16 nMode = pHostApp->getMtMode();

//set mt loading mode
SETBIT_1(nMode, 1);
pHostApp->setMtMode(nMode);
MyServices* pMyHostApp = dynamic_cast<MyServices*>(pHostApp);

//if our pHostApp contain override method for thread count's getting – then set 8 threads, for example
if (pMyHostApp != nullptr)
  pMyHostApp->setNumThreads(8);
OdNwDatabasePtr pDb = pHostApp->readFile(nwFile);
//… 

The following table shows the time decrease in multi-threaded loading when compared with single-threaded mode:

  Partial loading Full loading
  st vs mt2 st vs mt4 st vs mt8 st vs mt2 st vs mt4 st vs mt8
Average
improvements
-9% -20% -16% -7% -35% -38%

 

Multi-Threaded Regeneration

For multi-threaded regeneration while using Gi/Gs vectorization, you can set the thread count as a GS device property:

//...
OdNwHostAppServices* pHostApp;
OdGsDevicePtr pDevice;
OdString nwFile;
OdUInt32 mtRegenThreadCnt;
//...
OdNwDatabasePtr pDb = pHostApp->readFile(nwFile);
//...
// Initialize GsDevice and set additional properties to GiContext
//...
OdRxDictionaryPtr devProperties = pDevice->properties();
devProperties->putAt(OD_T("EnableMultithread"), OdRxVariantValue(true));
devProperties->putAt(OD_T("MaxRegenThreads"), OdRxVariantValue(static_cast<OdUInt16>(mtRegenThreadCnt)));
//…
//now update of Gs device is going in mt-regen mode
pDevice->update();
//...

For off-screen vectorization devices, set the GS device property ForcePartialUpdate to true:

//…
devProperties->putAt(OD_T("ForcePartialUpdate"), OdRxVariantValue(true));
//…

The following table shows the time decrease in multi-threaded regeneration when compared with single-threaded mode:

  st vs mt2 st vs mt4 st vs mt8
Average
improvements
-28% -45% -42%

The following hardware was used to get the statistics:

  • Intel® Core™ i7-6700 CPU @ 3.40GHz; 1 socket, 4 cores, 8 logical processors
  • 32GB RAM, speed 2133MHz
  • HDD

Find out more in our documentation.