正如@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;
您必须将for 与parallel 分开以避免在for 上使用隐式nowait 子句
编辑:如@Zulan所述
1) 如果发生取消,必须至少有一个所有线程可以自然到达的取消点。尽管cancel 指令本身根据定义有一个取消点,但它位于一个可能不会被所有线程访问的 if 语句中。解决方案是在 if 语句之外添加 cancellation point。我更改了代码以匹配此。
2) 在大多数运行时默认情况下禁用取消。要启用,应将OMP_CANCELLATION 环境变量设置为true。
3) a_output 中仍有竞争条件。除非您确定在t0 内只有一个值小于t_input,否则在取消发生之前有两个或更多线程将写入a_output。您应该查看代码背后的逻辑,以确认这是否存在问题。