C ++ OpenMP for循环全局变量问题

时间:2012-12-26 03:36:29

标签: c++ multithreading for-loop openmp

我是OpenMP的新手,从我读过的关于OpenMP 2.0(Microsoft Visual Studio 2010标准版)的内容来看,全局变量在并行编程中使用时会被认为很麻烦且容易出错。我也一直在采用这种感觉,因为我发现很少有关于如何有效地处理全局变量和静态全局变量,或根本没有。

我有这段代码运行,但由于在并行块中创建的局部变量,我没有得到我正在寻找的答案。我得到8种不同的打印输出(因为我的PC上有多少个线程)而不是1个答案。我知道这是因为并行块中创建的局部变量“list”,但如果我移动“list”变量并使其成为全局变量,则此代码将不会运行。实际上代码确实运行但它从来没有给我回答。这是我想要修改以使用全局“列表”变量的示例代码:

#pragma omp parallel
{
    vector<int> list;
#pragma  omp for
    for(int i = 0; i < 50000; i++) 
    {
        list.push_back(i);
    }
    cout << list.size() << endl;
}

输出:

6250
6250
6250
6250
6250
6250
6250
6250

他们加起来达到50000,但我没有得到50000的答案,而是分开了。

解决方案:

    vector<int> list;
    #pragma omp parallel
{
    #pragma  omp for
    for(int i = 0; i < 50000; i++) 
    {
        cout << i << endl;
    #pragma omp critical
        {
            list.push_back(i);
        }
    }
}
cout << list.size() << endl;

2 个答案:

答案 0 :(得分:1)

根据MSDN Documentation并行条款

  

定义一个并行区域,这是将由其执行的代码   多个线程并行。

由于list变量是在此部分内声明的,因此每个线程都有自己的列表。

另一方面,for pragma

  

使并行区域内的for循环完成工作   在线程之间划分。

因此,50000次迭代将在线程之间进行分割,但每个线程都有自己的列表。 我认为你要做的事情可以通过以下方式实现:

  1. 将列表定义放在“并行”部分之外。
  2. 使用critical section保护list.push_back语句。
  3. 试试这个:

    vector<int> list;
    #pragma omp parallel
    {
    #pragma  omp for
        for(int i = 0; i < 50000; i++) 
        {
    #pragma omp critical
            {
                list.push_back(i);
            }
        }
    }
    cout << list.size() << endl;
    

    在这种情况下,我认为你不应该从OpenMP获得任何加速,因为会有关键部分的争用。更快的解决方案(如果你不关心元素的顺序)将是每个线程都有自己的列表,并在循环结束后合并这些列表。在这种情况下,使用std :: list而不是std :: vector的实现看起来更干净(因为你不必复制数组)。

    某些应用程序受内存限制,不受计算限制。底线:检查您是否真的从OpenMP获得了加速。

答案 1 :(得分:0)

为什么你需要第一个pragma? (#pragma omp parallel)。我认为这就是问题所在。