简体   繁体   English

OpenMP 关于 for 循环

[英]OpenMP about for loop

I have a OpenMP code snippet as follows:我有一个 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;
        }
    }

Is this code correct?这段代码正确吗? Why a_output has to be private?为什么a_output必须是私有的? Can it be shared?可以共享吗?

As @1201ProgramAlarm said, you cannot have a return statement inside a parallel region.正如@1201ProgramAlarm 所说,并行区域内不能有return语句。 The compilers do not even compile the code编译器甚至不编译代码

$ 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.

However, the version 4.0 of the OpenMP specification brings a new directive: cancel .但是,OpenMP 规范的 4.0 版带来了一个新指令: cancel With it, you can interrupt the execution of a parallel region.有了它,您可以中断并行区域的执行。 It adds a bit of overhead to the total execution time because in each iteration the threads test whether they have to stop or not.它给总执行时间增加了一些开销,因为在每次迭代中,线程都会测试它们是否必须停止。

You can try rewrite the original for-loop this way:您可以尝试以这种方式重写原始 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;

You must separate the for from parallel to avoid use a implicit nowait clause on for您必须将forparallel分开以避免在 for 上使用隐式nowait子句

EDIT: as stated by @Zulan编辑:如@Zulan所述

1) There must be at least one cancellation point that all threads can naturally reach if a cancellation should occur. 1)如果发生取消,必须至少有一个所有线程可以自然到达的取消点。 Although the cancel directive itself has a cancellation point by definition, it is within an if statement that may not be accessed by all threads.尽管根据定义cancel指令本身有一个取消点,但它位于一个 if 语句中,可能不是所有线程都可以访问的。 The solution to this is to add a cancellation point outside the if statement.解决这个问题的方法是在 if 语句之外添加一个cancellation point I changed the code to match this.我更改了代码以匹配此内容。

2) The cancellation is disabled by default in most runtimes. 2) 在大多数运行时默认情况下禁用取消。 To enable, one should set the OMP_CANCELLATION environment variable to true.要启用,应将OMP_CANCELLATION环境变量设置为 true。

3) There is still a race condition in a_output . 3) a_output仍然存在竞争条件。 Unless you are sure that there is only one value less than t_input within t0 , there is a possibility that two or more threads will write to a_output before cancellation occurs.除非您确定t0内只有一个值小于t_inputt_input有可能两个或多个线程在取消之前写入a_output You should review the logic behind your code to confirm if this is a problem or not.您应该查看代码背后的逻辑以确认这是否是一个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM