1

我是 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;
4

2 回答 2

1

根据MSDN 文档并行子句

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

由于列表变量是在本节中声明的,因此每个线程都有自己的列表。

另一方面,for pragma

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

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

  1. 将列表定义置于“并行”部分之外。
  2. 临界区保护 list.push_back 语句。

试试这个:

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 获得了加速。

于 2012-12-26T04:03:49.487 回答
0

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

于 2012-12-26T03:57:27.177 回答