首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用OpenMP使用全局外部变量的私有版本

使用OpenMP使用全局外部变量的私有版本
EN

Stack Overflow用户
提问于 2019-08-16 16:07:57
回答 1查看 314关注 0票数 0

我有两个全局外部变量。我希望每个线程都有自己的私有副本,并共享另一个线程的副本。目标是让每个线程在私有版本上工作,然后将信息合并到第二个版本中。

这看起来可能有点过分,但这是我真正在做的事情的MWE:

外部变量在Globals.h文件中定义:

代码语言:javascript
复制
extern vector<int> TestVector;
extern vector<vector<int>> CombinedTestVector;

Globals.cpp文件中:

代码语言:javascript
复制
vector<int> TestVector;
vector<vector<int>> CombinedTestVector;

已执行的MyFunc.cpp (包括Globals.h)

代码语言:javascript
复制
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

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-08-16 16:23:34

这里似乎对firstprivate和相关的实际操作存在误解。他们没有做的是神奇地让全局变量引用每个线程中的不同副本。相反,它们会在本地作用域中给出一个副本(如果使用firstprivate,则从全局作用域中复制)。

把它想成这样:

代码语言:javascript
复制
#   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,这是非常令人关注的。
  • 我鼓励变量和函数从小写字母开始,而不是大写字母。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57527849

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档