1
#include "/usr/lib/gcc/i686-linux-gnu/4.6/include/omp.h"
#include <iostream>
#include<list>
using namespace std;

int main()
{
    list<int> lst;
    for(int i=0;i<5;i++)
        lst.push_back(i);

#pragma omp parallel for
    for(int i=0;i<5;i++)
    {
        cout<<i<<" "<<omp_get_thread_num()<<endl;
    }   
}

假设我可以得到这个:

0  0
1  0
2  0
3  1
4  1

但是,有时我可以得到这个结果:

30  0
1  0
2  0
  1
4  1

甚至是这种结果:

30 1 0
4 1

1 0
2 0

我知道这是因为输出代码:

cout<<i<<" "<<omp_get_thread_num()<<endl;

已经被拼接成小段,做输出时没有顺序。但是谁能告诉我如何防止这种情况发生?谢谢。

4

4 回答 4

3

标准输出流不同步!

标准给出的唯一保证是,单个字符是原子输出的。

您需要一个锁 - 这违背了并行化的点,或者您可以删除应该导致准同步行为的“<< i”。

于 2013-01-24T10:27:38.590 回答
1

循环无序运行。这就是为什么你有无序的输出。

如果你的问题30

30  0
1  0
2  0
 1
4  1

然后保持冷静,没有30,但是30。正如预期的那样,您仍然有一个无序的行[0..4]

3 0  0
1  0
2  0
 1
4  1

你不能说的只是哪个0s 中的哪个1不是线程号。

于 2013-01-24T10:46:50.303 回答
0

你的代码

#pragma omp parallel for
    for(int i = 0; i < 5; i++)
    {
        cout << i << " " << omp_get_thread_num() << endl;
    }

相当于

#pragma omp parallel for
    for(int i = 0; i < 5; i++)
    {
        cout << i;
        cout << " ";
        cout << omp_get_thread_num();
        cout << endl;
    }

不同线程中的调用<<可以按任何顺序执行。例如cout << i;,线程 3 后面可能跟在线程cout << i;0 后面,而线程 0 后面可能跟cout << " ";在线程 3 中等等,从而导致输出乱码30 ...

正确的做法是重写代码,让每个线程cout <<在循环中只调用一次:

#pragma omp parallel for
    for(int i = 0; i < 5; i++)
    {
        stringstream ss;
        ss << i << " " << omp_get_thread_num() << '\n';
        cout << ss.str();
    }   
于 2013-01-24T12:42:45.610 回答
0

您可以创建一个数组(大小5),其中包含哪个线程处理了哪个索引,然后在并行循环之外打印它。

于 2013-01-24T10:30:53.003 回答