我正在尝试学习并行计算的基础知识,但我在计算机上遇到了一个问题。看看下面的代码。基本上,我想打印出#34; Hello World!"我的电脑拥有的每一个核心。我的电脑有四个核心,因此它应打印出该行四次。如果我要使用已注释掉的' cout'而不是' printf'线,输出将全部混乱。这是因为' \ n' escape命令与" Hello World!"分开执行,因此新行输出将随机发生。 ' printf' line是这个问题的解决方案,因为该行是一次性执行的(不会分成像' cout'行这样的部分)。但是,当我使用' printf'时,我的输出仍然混乱,好像我使用了' cout'。我不知道为什么会这样做。我在另一台计算机上尝试了完全相同的代码,它完美无缺。只有我的电脑才能继续使用> printf'混淆输出。我已经通过电子邮件向我的CS教授发了电子邮件,他不知道为什么要在我的电脑上这样做。我知道我在计算机上正确设置了OpenMP。有并行计算经验的人是否知道为什么这会弄乱我的电脑?
#include <omp.h>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
#pragma omp parallel
{
printf("Hello World!\n");
//cout << "Hello World!\n" << endl;
}
return 0;
}
为了显示我正在谈论的内容,以下是我在计算机上运行上述代码时的输出:
Hello Wo
Hello World!
RLD!
Hello World!
答案 0 :(得分:7)
对不起,你的教授错了。您需要利用互斥或其他障碍,以保证不间断使用共享资源(在本例中为STDOUT
输出文件)。
混合输出是潜在的预期行为,无论printf
还是std::cout::operator<<()
。由于设计的不同,您看到的行为差异是每个行为的执行持续时间的细微差别。在任何一种情况下都应该期待这种行为。
我只是不明白为什么它会为其他人工作。
不是。成为班上的英雄并解释它是如何工作的以及如何解决它。告诉他们SO发送他们的爱。 :)
答案 1 :(得分:5)
正如已经解释的那样,假设printf()
是原子的并且不会破坏你的输出而std::cout::operator<<()
不是,如果从根本上是错误的话会搞砸。
然而,仍有一小部分真相&#34;在这,但在不同的水平。让我举个例子:
如果我尝试OpenMP&#34; Hello world&#34; 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次,只有可能会或可能不会发送到标准输出的位和多条线。
在内部,任何事情都可能发生,我不会尝试对任何行为做出承诺。但至少在这里使用printf()
,即使我无法保证,我也会增加清洁输出的机会。
以下是一个完整的例子:
#include <iostream>
#include <stdio.h>
#include <omp.h>
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()
是原子的并且不会搞砸是错误的,但简单地说,对于复杂的输出字符串,它比std::cout
更不容易被破坏。