我有一台2.16 GHz的AMD Athlon II P320双核处理器。
我正在尝试运行以下程序,但它似乎仅由一个核心处理。
#include <stdio.h>
#include <omp.h>
int main (void){
int i;
#pragma omp parallel for
for ( i = 1; i < 100; i++){
printf("%d ", i);
fflush(stdout);
}
}
我期望输出是随机顺序中的前99个数字,但是我的输出是ascendent顺序中的前99个数字。这有什么问题?
答案 0 :(得分:2)
我已经在双核(或在四核或更多核上设置omp_set_num_threads(2)
)和 Windows 进行了测试,我能够看到你的结果。对于ChirsBD的答案,编译器不能忽略这样的printf
。 OP的代码将被并行化并将并行运行。
您正在使用默认的OpenMP静态调度并使用2个内核。因此,第一个核心将从1到50打印出来,另一个核心从51到100打印。但是,观察结果是你看不到一些比赛。
printf
和fflush
也会被序列化。因此,第一个线程很可能获取该互斥锁,第二个线程将被阻止。
但是,这个简单的printf
计算太短了。因此,当第二个线程被阻止第一次尝试获取临界区时,第一个线程只打印整个数字。这意味着,{获取和释放关键部分50次的时间}&lt; {最小阻塞第二个线程的时间}。
如果你进行虚拟计算,例如for (volatile int k = 0; k < 100; ++k);
,你会看到交错,但仍然锁定steped:输出主要是"1 51 2 52 ..."
。
但是,当我在Linux上运行此代码时,我看到一些随机排序。这是因为Linux中stdout的实现和内部锁定可能与Windows不同。
总而言之,这种序列化是由于实现printf
和并行循环中的计算太短。因此,不是一个问题。
答案 1 :(得分:1)
由于您在同一输出流上执行printf
,因此对此循环进行Parellizing是无效的。输出到这样的流是互斥的,因此即使openMP设法启动单独的线程,它们也将被强制顺序访问该资源。
让线程写入不同的文件,每个文件,你可能会看到不同。但要真正看到一个,你应该在内部部分有一些计算绑定而不是IO绑定。
答案 2 :(得分:0)
我怀疑,因为这是一个简单的过程,编译器优化优先。
尝试将其写为对自身的递归函数调用而不是循环,然后看看会发生什么。
答案 3 :(得分:0)
您获得该输出的原因是因为默认情况下openMP使用静态分区。因此,对于两个内核,它会将间隔0..100划分为0..50和51..100。现在,由于间隔非常小,因此一个线程打印50个数字(很可能)会在另一个线程甚至设法启动之前发生。这就是你看到连续数字而不是交错的原因。