使用OpenMP“无效控制谓词”编译器错误
我正在创建一个基本的素数检查器,基于C – 确定一个数字是否是素数 ,但是使用OpenMP。
int isPrime(int value) { omp_set_num_threads(4); #pragma omp parallel for for( int j = 2; j * j <= value; j++) { if ( value % j == 0) return 0; } return value; }
使用-fopenmp进行编译时,GCC版本4.7.2发生错误,声明了与for循环相关的invalid controlling predicate
。
看起来这个错误是由for循环中的j平方引起的。 有没有办法解决这个问题,仍然可以从算法中获得所需的输出?
循环内部不允许return
,因为它会导致花括号前退出。
请注意下面给出的定义:
从OpenMP V2.5规范,1.2.2 OpenMP语言术语,p2:17-
结构化块 – 对于C / C ++,一种可执行语句,可能是复合语句,顶部有一个条目,底部有一个出口。
结构化块以open {
开头,以结束}
结束。 return
包含在这些大括号中,因此该程序也违反了结构化块的OpenMP定义,因为它有两个出口(一个在return
,一个在出口处通过大括号)
OpenMP对可以线程化的循环放置以下五个限制:
- 循环变量必须是有符号整数类型。 无符号整数,如DWORD,将无法正常工作。
- 比较操作必须采用loop_variable
<
,<=
,>
或>=
loop_invariant_integer的forms - for循环的第三个表达式或增量部分必须是整数加法或整数减法,并且必须是循环不变值。
- 如果比较操作是
<
或<=
,则循环变量必须在每次迭代时递增,相反,如果比较操作是>
或>=
,则循环变量必须在每次迭代时递减。 - 循环必须是一个基本块,这意味着除了exit语句之外,不允许从循环内部跳转到外部,这将终止整个应用程序。 如果使用语句goto或break,它们必须在循环内跳转,而不是在循环之外。 exception处理也是如此; 必须在循环内捕获exception。
根据OpenMP标准(§2.5.1,p.40), for
循环的控制谓词的可接受forms是:
- var relational-op b ,和
- b关系型变种
您使用j * j <= value
明显违反了此要求。 其基本原理是它要求编译器发出在运行时计算value
的整数平方根的代码,后者对于某些值的value
是未定义的,特别是对于负值。
您可以用j <= sqrt_value
替换j * j <= value
,其中sqrt_value
是value
的整数平方根,但是在循环内的结构化块中具有替代退出路径会产生问题。 遗憾的是,在这种情况下不存在简单的解决方案,因为OpenMP不支持并行循环的提前终止。