在一个函数调用中创建一个线程池并从另一个函数调用中使用它

Creating a thread pool in one function call and using it from another function call

我有一个 Fortran 程序调用 C++ dll 对 10000 组数据进行一些数学运算。数据集彼此完全独立。我打算创建一个线程池,然后向它发送任务。但是dll的调用会超过1000次(每次调用处理10000组数据)。

我的问题是:当我在第一次调用 dll 期间创建线程池时,在 dll 中的函数之后该线程池会发生什么情况 returns?第二次调用(以及剩余的 998 次调用)能否访问在第一次调用期间创建的池。

如果设置正确,您确实可以使用相同的线程池。

在 FORTRAN->C++ 调用线程的堆栈上创建的对象将随着堆栈展开和控制 returns 到 FORTRAN 被销毁,因此将线程池管理数据放在上面不是一个好主意堆。但是,您可以:

  • 启动另一个创建线程池管理的线程data/object,或
  • 在堆上分配(使用 new)以将生命周期与 FORTRAN->C++ 调用分离。

后者可能更简单更干净...指向管理线程池的堆 object/data 的指针可以返回给 FORTRAN 并用作 "handle" 以供将来调用,表示相同应该使用线程池。

如果您可以控制 Fortran 代码,则可以通过使用 3 个函数而不是一个函数来避免偷偷摸摸地隐藏您维护的状态。

someStateHandle PrepareBackgroundWork();
// Then you do your actual call series...
DoMyMath(someStateHandle, args...);

// And when you are done with all that, you call
FinalizeBackgroundWork(someStateHandle);

如果您无法控制 Fortran 代码,则必须决定要保留什么(线程池内容或线程句柄和一些同步对象)并延迟初始化它们。

struct MyWorkerContext
{
    size_t numberOfWorkerThreads;
    std::vector<HANDLE> workerHandles; 
    // ...
};
static MyWorkerContext* s_context = NULL; // Sorry - looks like a singleton to me.
void DoMyMath( args..)
{
    if(NULL == s_context) InitializeContext();
    if( NULL != s_context )
    {
         // do the calculations using all that infrastructure.
    }
}

E.g. in DLLMain() or hopefully earlier: clean up s_context.

最后一点,我认为有一个 "default thread pool",您也可以使用它而不是创建自己的。