我有两个全局外部变量。我希望每个线程都有自己的私有副本,并共享另一个线程的副本。目标是让每个线程在私有版本上工作,然后将信息合并到第二个版本中。
这看起来可能有点过分,但这是我真正在做的事情的MWE:
外部变量在Globals.h文件中定义:
extern vector<int> TestVector;
extern vector<vector<int>> CombinedTestVector;在Globals.cpp文件中:
vector<int> TestVector;
vector<vector<int>> CombinedTestVector;已执行的MyFunc.cpp (包括Globals.h)
void MyFunc(int NumberOfIterations)
{
int iter;
SetupTestVector();
cout << "Test vector initially looks like:\n";
PrintTestVector();
# pragma omp parallel for default(shared) private(iter) firstprivate(TestVector)
for (iter = 0; iter < NumberOfIterations; iter++)
{
int MyThreadNum = omp_get_thread_num();
RemoveOneFromYourThreadIndex(MyThreadNum);
# pragma omp critical
{
cout << " Thread " << MyThreadNum << ", TestVector now looks like:\n";
cout << " ";
PrintTestVector();
}
CombinedTestVector.push_back(TestVector);
}
# pragma omp barrier
cout << "Combined vector looks like:\n";
PrintCombinedVector();
}
///////////////////////////////////////////////////////////////////////
void SetupTestVector()
{
TestVector.push_back(10);
TestVector.push_back(11);
TestVector.push_back(12);
TestVector.push_back(13);
TestVector.push_back(14);
}
///////////////////////////////////////////////////////////////////////
void PrintTestVector()
{
for (size_t i = 0; i < TestVector.size(); i++)
{
cout << TestVector.at(i) << " ";
}
cout << "\n";
}
///////////////////////////////////////////////////////////////////////
void RemoveOneFromYourThreadIndex(int ThreadIndex)
{
TestVector.at(ThreadIndex) -= 1;
TestVector.push_back(ThreadIndex);
}
///////////////////////////////////////////////////////////////////////
void PrintCombinedVector()
{
for (size_t i = 0; i < CombinedTestVector.size(); i++)
{
for (size_t j = 0; j < CombinedTestVector.at(i).size(); j++)
{
cout << CombinedTestVector.at(i).at(j) << " ";
}
cout << "\n";
}
cout << "\n";
}如果使用NumberOfIterations = 1执行此操作,则会得到:
测试向量最初看起来如下: 10 11 12 13 14 TestVector现在看起来像: 新界区9 11 12 13 14 0 组合向量看起来如下: 10 11 12 13 14
所以你可以看到组合向量没有得到我想要的.如果使用3个线程执行,则更糟糕的是:
测试向量最初看起来如下: 10 11 12 13 14等高线2,TestVector现在看起来像: 9 10 11 13 14 2 0 1 TestVector现在看起来像: 9 10 11 13 14 2 0 1 TestVector现在看起来像: 9 10 11 13 14 2 0 1 组合向量看起来如下: 10 11 12 13 14 10 10 11 13 14 2 10 11 12 13 14
我如何才能得到预期的行为,也就是:
测试向量最初看起来如下: 10 11 12 13 14等高线0,TestVector现在看起来如下: 新界区9 11 12 13 14 0 TestVector现在看起来像: 10 10 12 13 14 1 TestVector现在看起来像: 10 11 11 13 14 2 组合向量看起来如下: 11 12 13 14 0 10 10 12 13 14 1 10 11 11 13 14 2
发布于 2019-08-16 16:23:34
这里似乎对firstprivate和相关的实际操作存在误解。他们没有做的是神奇地让全局变量引用每个线程中的不同副本。相反,它们会在本地作用域中给出一个副本(如果使用firstprivate,则从全局作用域中复制)。
把它想成这样:
# pragma omp parallel for default(shared) private(iter) firstprivate(TestVector)
for (iter = 0; iter < NumberOfIterations; iter++)
{
thread_local vector<int> TestVector = ::TestVector; /* OMP MAGIC */
int MyThreadNum = omp_get_thread_num();
// etc. ...lots of stuff that completely ignores your local copy
// (The function calls still operate on the global TestVector!)
CombinedTestVector.push_back(TestVector);
}那么问题就很明显了:在RemoveOneFromYourThreadIndex中,您引用的是全局TestVector,而不是在您的小节中使用firstprivate的那个。您需要将这个本地实例传递到RemoveOneFromYourThreadIndex (以及应该在TestVector上操作的所有其他函数)。
另外,CombinedTestVector.push_back(TestVector);是不同步的,因此是一个竞争条件,您也应该修复它。
Misc关于代码质量的评论:
using namespace std;。Globals.h,这是非常令人关注的。https://stackoverflow.com/questions/57527849
复制相似问题