并行计算——混淆了输出?
Parallel computing -- jumbled up output?
我正在尝试学习并行计算的基础知识,但我 运行 在我的计算机上遇到了问题。看看下面我的代码。基本上,我想打印出“Hello World!”这一行。对于我的计算机的每个核心。我的电脑有四个核心,所以它应该打印四次该行。如果我使用注释掉的 'cout' 行而不是 'printf' 行,输出将全部混乱。这是因为 '\n' 转义命令与 "Hello World!" 分开执行,所以换行输出会 运行domly 发生。 'printf' 行是这个问题的解决方案,因为该行是一次性执行的(不像 '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!
抱歉,您的教授弄错了。您需要利用互斥或其他一些障碍来保证不间断地使用共享资源(在本例中是 STDOUT
输出文件)。
混合输出是潜在的预期行为,无论 printf
还是 std::cout::operator<<()
。由于设计不同,您看到的行为差异是每个行为的执行持续时间的细微差异。在任何一种情况下,您都应该期待这种行为。
I just don't understand why it would be working for everyone else.
不是。成为您 class 的英雄并解释它的工作原理和修复方法。告诉他们 SO 发送他们的爱。 :)
如前所述,假设 printf()
是原子的,不会破坏您的输出,而 std::cout::operator<<()
不是,如果从根本上是错误的,将会把事情搞砸。
不过,这里面还有"truth"的(微小的)一部分,只是层次不同而已。让我举个例子:
如果我尝试 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次,只有一些行可能会或可能不会发送到标准输出。
在内部,任何事情都可能发生,我不会尝试做出任何行为。但至少通过在这里使用 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$
如果你仔细观察,你会发现 none 对 std::cout::operator<<()
的单独调用是分开的,但每个新调用都是不同线程相互竞争的机会,并且使输出混乱。
所以再说一遍,说 printf()
是原子的并且不会把事情搞砸是错误的,但简单地说,对于一个复杂的输出字符串,它比 std::cout
更不容易被破坏.
我正在尝试学习并行计算的基础知识,但我 运行 在我的计算机上遇到了问题。看看下面我的代码。基本上,我想打印出“Hello World!”这一行。对于我的计算机的每个核心。我的电脑有四个核心,所以它应该打印四次该行。如果我使用注释掉的 'cout' 行而不是 'printf' 行,输出将全部混乱。这是因为 '\n' 转义命令与 "Hello World!" 分开执行,所以换行输出会 运行domly 发生。 'printf' 行是这个问题的解决方案,因为该行是一次性执行的(不像 '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!
抱歉,您的教授弄错了。您需要利用互斥或其他一些障碍来保证不间断地使用共享资源(在本例中是 STDOUT
输出文件)。
混合输出是潜在的预期行为,无论 printf
还是 std::cout::operator<<()
。由于设计不同,您看到的行为差异是每个行为的执行持续时间的细微差异。在任何一种情况下,您都应该期待这种行为。
I just don't understand why it would be working for everyone else.
不是。成为您 class 的英雄并解释它的工作原理和修复方法。告诉他们 SO 发送他们的爱。 :)
如前所述,假设 printf()
是原子的,不会破坏您的输出,而 std::cout::operator<<()
不是,如果从根本上是错误的,将会把事情搞砸。
不过,这里面还有"truth"的(微小的)一部分,只是层次不同而已。让我举个例子:
如果我尝试 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次,只有一些行可能会或可能不会发送到标准输出。
在内部,任何事情都可能发生,我不会尝试做出任何行为。但至少通过在这里使用 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$
如果你仔细观察,你会发现 none 对 std::cout::operator<<()
的单独调用是分开的,但每个新调用都是不同线程相互竞争的机会,并且使输出混乱。
所以再说一遍,说 printf()
是原子的并且不会把事情搞砸是错误的,但简单地说,对于一个复杂的输出字符串,它比 std::cout
更不容易被破坏.