c - OpenMP 关于 for 循环

标签 c for-loop openmp

我有一个 OpenMP 代码片段,如下所示:

#ifdef _OPENMP
  #pragma omp parallel for default(none) \
  private(i, a_output) \
  shared(n, t_input, t0, trace_amp)
#endif
    for (i = 0; i < n; i++){
        if( t_input >= t0[i] )
        {

                a_output = trace_amp[i];

                return a_output;
        }
    }

这段代码正确吗?为什么a_output必须是私有(private)的?可以分享吗?

最佳答案

正如@1201ProgramAlarm所说,并行区域内不能有return语句。编译器甚至不编译代码

$ gcc Untitled-1.c -fopenmp
Untitled-1.c: In function ‘main’:
Untitled-1.c:7:20: error: invalid branch to/from OpenMP structured block
             return a_output;

$ clang Untitled-1.c -fopenmp=libomp
Untitled-1.c:7:13: error: cannot return from OpenMP region
            return a_output;
            ^
1 error generated.

但是,OpenMP 规范 4.0 版本带来了一个新指令:cancel。有了它,您可以中断并行区域的执行。它给总执行时间增加了一点开销,因为在每次迭代中线程都会测试它们是否必须停止。

您可以尝试这样重写原始的 for 循环:

  a_output = 0;
#ifdef _OPENMP
  #pragma omp parallel default(none) \
  private(i) \
  shared(n, t_input, t0, trace_amp, a_output)
  #pragma omp for
#endif
  for (i = 0; i < n; i++){
      if( t_input >= t0[i] ){
              a_output = trace_amp[i];
              #pragma omp cancel for
      }
      #pragma omp cancellation point for

  }
  return a_output;

您必须将 forparallel 分开,以避免在 for 上使用隐式 nowait 子句

编辑:如@Zulan所述

1) 如果发生取消,则必须至少有一个所有线程都能自然到达的取消点。尽管按照定义,cancel 指令本身有一个取消点,但它位于 if 语句内,可能无法被所有线程访问。解决方案是在 if 语句外部添加一个取消点。我更改了代码以匹配此内容。

2) 在大多数运行时,取消功能默认处于禁用状态。要启用此功能,应将 OMP_CANCELLATION 环境变量设置为 true。

3) a_output 中仍然存在竞争条件。除非您确定 t0 中只有一个值小于 t_input,否则有可能有两个或多个线程写入 a_output在取消发生之前。您应该检查代码背后的逻辑,以确认这是否有问题。

关于c - OpenMP 关于 for 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57311449/

相关文章:

c - 使用 C - 字符串中有\n\r (ascii) 字符串,我想将其转换为实际的换行符 CR

python - 以下 for 循环如何工作?

C 数组 - 对错误输入的错误响应?

c++ - 多线程在 c++ 中的递归函数,编辑..使用 OpenMP 比以前慢

Power8 上的 OpenMP SIMD

c - 使用 netcat 允许用户使用 shell

c - 链接器错误 : what could be going on?

for-loop - 如何使用 openscad/for-loop 在立方体上打洞?

c++ - C++ OpenMP 中线性代数函数的高效并行化

c - Solaris 64 位上的函数指针导致堆损坏