在一个函数调用中创建一个线程池并从另一个函数调用中使用它
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",您也可以使用它而不是创建自己的。
我有一个 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",您也可以使用它而不是创建自己的。