并行计算 – 输出混乱?

我正在尝试学习并行计算的基础知识,但我在计算机上遇到了一个问题。 看看下面的代码。 基本上,我想打印出“Hello World!”这一行。 我的电脑拥有的每一个核心。 我的电脑有四个核心,因此它应打印出该行四次。 如果我使用已注释掉的’cout’行而不是’printf’行,输出将全部混乱。 这是因为’\ n’转义命令与“Hello World!”分开执行,因此新行输出将随机发生。 ‘printf’行是这个问题的解决方案,因为该行是一次性执行的(不会分成像’cout’行这样的部分)。 但是,当我使用’printf’时,我的输出仍然混乱,就像我使用’cout’一样。 我不知道为什么会这样做。 我在另一台计算机上尝试了完全相同的代码,它完美无缺。 只有我的电脑继续使用’printf’混淆输出。 我已经通过电子邮件向我的CS教授发了电子邮件,他不知道为什么要在我的电脑上这样做。 我知道我在计算机上正确设置了OpenMP。 有并行计算经验的人是否知道为什么这会弄乱我的电脑?

#include  #include  #include  #include  using namespace std; int main() { #pragma omp parallel { printf("Hello World!\n"); //cout << "Hello World!\n" << endl; } return 0; } 

为了显示我正在谈论的内容,这是我在计算机上运行上述代码时的输出:

你好禾

你好,世界!

RLD!

你好,世界!

对不起,你的教授错了。 您需要利用互斥或其他障碍,以保证不间断使用共享资源(在本例中为STDOUT输出文件)。

无论printf还是std::cout::operator<<()混合输出都是潜在的预期行为。 由于设计的不同,您看到的行为差异是每个行为的执行持续时间的细微差别。 在任何一种情况下都应该期待这种行为。

我只是不明白为什么它会为其他人工作。

不是。 成为class上的英雄并解释它是如何工作的以及如何解决它。 告诉他们SO发送他们的爱。 :)

正如已经解释过的那样,假设printf()是primefaces的并且不会破坏你的输出,而std::cout::operator<<()则不会,如果从根本上错误的话就会搞砸了。

然而,在这方面仍有一小部分“真相”,但处于不同的层面。 让我给你举个例子:

如果我尝试OpenMP“Hello world”C风格,那可能会给出:

 printf( "Hello from thread %d of %d\n", omp_get_thread_num(), omp_get_num_threads() ); 

同样的C ++风格可能如下所示:

 std::cout << "Hello from thread " << omp_get_thread_num() << " of " << omp_get_num_threads() << std::endl; 

两者之间的本质区别在于,对于printf() ,我只用一个完全准备好的输出字符串调用一次打印方法,而C ++风格的一个将调用std::cout::operator<<() 5次,只有可能会或可能不会发送到标准输出的位和行。 在内部,任何事情都可能发生,我不会尝试任何forms的行为。 但至少在这里使用printf() ,即使我无法保证,我也增加了输出干净的机会。

这是一个完整的例子:

 #include  #include  #include  int main() { #pragma omp parallel printf( "Hello from thread %d of %d with printf()\n", omp_get_thread_num(), omp_get_num_threads() ); printf( "*** outside of parallel region ***\n" ); #pragma omp parallel std::cout << "Hello from thread " << omp_get_thread_num() << " of " << omp_get_num_threads() << " with std::cout" << std::endl; return 0; } 

在我的Linux笔记本电脑上给我(GCC 5.2):

 ~/tmp$ g++ -fopenmp stdout.cc ~/tmp$ ./a.out Hello from thread 3 of 4 with printf() Hello from thread 0 of 4 with printf() Hello from thread 2 of 4 with printf() Hello from thread 1 of 4 with printf() *** outside of parallel region *** Hello from thread Hello from thread Hello from thread Hello from thread 1 of 4 with std::cout23 of 4 with std::cout of 4 with std::cout 0 of 4 with std::cout ~/tmp$ 

如果仔细观察,你可以看到对std::cout::operator<<()的单独调用都没有被拆分,但每次新调用都是各个线程相互竞争的机会,并获得输出错位。

再说一次,告诉printf()是primefaces的并且不会搞砸是错误的,但简单地说,对于复杂的输出字符串,它比使用std::cout更不容易被破坏。