使用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_valuevalue的整数平方根,但是在循环内的结构化块中具有替代退出路径会产生问题。 遗憾的是,在这种情况下不存在简单的解决方案,因为OpenMP不支持并行循环的提前终止。