底线
如何确保threadprivate实例被正确销毁?
背景
当回答this question时,我遇到了一个奇怪的问题,使用Intel C++ 15.0编译器在VS2013中声明全局变量threadprivate
时,从属线程的副本没有被销毁。我开始寻找强制销毁它们的方法。在this网站上,他们说添加OMP屏障应该有所帮助。但并没有(请参见MCVE)。我尝试将OMP块时间设置为0,以便线程不会在并行区域之后停留(也没有帮助)。我尝试添加一些虚拟计算来延迟主线程,使其他线程有时间死亡。仍然没有帮助。
MCVE:
#include <iostream>
#include <omp.h>
class myclass {
int _n;
public:
myclass(int n) : _n(n) { std::cout << "int c'tor\n"; }
myclass() : _n(0) { std::cout << "def c'tor\n"; }
myclass(const myclass & other) : _n(other._n)
{ std::cout << "copy c'tor\n"; }
~myclass() { std::cout << "bye bye\n"; }
void print() { std::cout << _n << "\n"; }
void add(int t) { _n += t; }
};
myclass globalClass;
#pragma omp threadprivate (globalClass)
int main(int argc, char* argv[])
{
std::cout << "\nBegninning main()\n";
// Kill the threads immediately
kmp_set_blocktime(0);
#pragma omp parallel
{
globalClass.add(omp_get_thread_num());
globalClass.print();
#pragma omp barrier
//Barrier doesn't help
}
// Try some busy work, takes a few seconds
double dummy = 0.0;
for (int i = 0; i < 199999999; i++)
{
dummy += (sin(i + 0.1));
}
std::cout << dummy << "\n";
std::cout << "Exiting main()\n";
return 0;
}
输出结果为:
构造函数
进入main()
构造函数
1
构造函数
3
构造函数
2
0
1.78691
退出main()
再见
我预期会有四个“再见”,但只有一个。
更新
根据Kyle引用的OMP 4.0标准,其中指出:
所有线程专用变量的所有副本的存储将按照基本语言中静态变量的处理方式进行释放,但在程序的某个未指定点进行。
我添加了该类的静态实例(全局和局部),以查看其析构函数是否被调用。它确实被调用,无论是对于局部还是全局情况。因此问题仍然存在。