[英]OpenMP about for loop
我有一个 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
必须是私有的? 可以共享吗?
正如@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
, t_input
有可能两个或多个线程在取消之前写入a_output
。 您应该查看代码背后的逻辑以确认这是否是一个问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.