Openmp并行部分与并行部分

时间:2013-03-25 14:55:22

标签: c parallel-processing openmp

我有这两段代码

#pragma omp parallel
#pragma omp sections
  {
#pragma omp section
    printf("H");
#pragma omp section
    printf("e");
#pragma omp section
    printf("l");
#pragma omp section
    printf("l");
#pragma omp section
    printf("o");
#pragma omp section
    printf(" ");
#pragma omp section
    printf("W");
#pragma omp section
    printf("o");
#pragma omp section
    printf("r");
#pragma omp section
    printf("l");
#pragma omp section
    printf("d");
#pragma omp section
    printf("!");
  }

char word[] = "Hello World!";
int n;

#pragma omp parallel for
  for(n=0; n<12; n++)
  {
  printf("%c", word[n]);
  }

虽然第一个总是打印Hello World!,但第二个有时打印Hello World!,有时会打印Helld!lo Wor

为什么第一个似乎是确定性的而另一个不是?

4 个答案:

答案 0 :(得分:7)

首先,官方GCC 4.1.2 支持OpenMP。可能你有一个RedHat派生的Linux发行版(RHEL,Fedora,CentOS,Scientific Linux等),它的OpenMP支持从一些较新的版本向后移植到GCC 4.1.2中。 RH用于维持该backport很长一段时间,直到他们最终切换到更新的GCC版本。

写入共享流会导致OpenMP部分和并行循环中出现非确定性行为。您在此处观察到的是GCC中sections实现的动态调度性质的结果。 libgomp(GCC OpenMP运行时)以先到先得的方式在团队中的线程之间分配部分。在您的情况下可能发生的情况是,部分的大小非常短,因此在执行时,在并行区域开始处退出对接障碍的第一个线程会消耗所有工作项,然后其他线程甚至会赶上,结果连续执行所有部分。

对于并行for循环,您观察到的是libgompstatic的默认循环调度的结果,即12个迭代均匀分配在线性时尚。我猜你的情况下有6个线程(基于来自加扰输出的文本段),因此线程0从0到1进行迭代,线程1从2到3进行迭代,依此类推。同样,每个线程中迭代的执行都得到了很好的定义,但是不能保证线程本身的执行顺序。

请注意,此行为非常符合GCC。 OpenMP标准说:

  

在团队中的线程之间调度结构化块的方法是   实施定义。

例如,英特尔的编译器以循环方式分发这些部分,即部分n被赋予线程n % num_threads,就像具有静态调度的并行for循环一样。块大小为1。

答案 1 :(得分:4)

如果你想让for循环做同样的事情,请使用&#34; ordered&#34;在你的for循环中这样:

#pragma omp parallel for ordered 
for(n=0; n<12; n++) {
    #pragma omp ordered
    printf("%c", word[n]);
}

查看此示例: http://bisqwit.iki.fi/story/howto/openmp/#ExampleCalculatingTheMandelbrotFractalInParallel

答案 2 :(得分:2)

omp parallel for不具有确定性。您应该使用此子句来实现算法,这些算法在数组中具有独立数据。如果要打印一些文本,则字母应按顺序逐个跟随,但omp parallel for以随机顺序执行代码。

答案 3 :(得分:2)

部分不是确定性的,也不是平行的。 OpenMP规范here没有说明确定性的部分。

我用2个主题运行你的部分代码并得到Hllo World!e

您的代码只是按顺序生成字母的机会。