使用OpenMP"无效控制谓词"编译器错误

Nic*_*ick 10 c 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;
}
Run Code Online (Sandbox Code Playgroud)

使用-fopenmp进行编译时,GCC版本4.7.2 出错,说明invalid controlling predicatefor循环.

看起来这个错误是由for循环中的j平方引起的.有没有办法解决这个问题,仍然可以从算法中获得所需的输出?

0de*_*al0 14

return 在循环中是不允许的,因为它会在花括号之前导致退出.

请注意下面给出的定义:

从OpenMP V2.5规范,1.2.2 OpenMP语言术语,p2:17-

结构化块 - 对于C/C++,一个可执行语句,可能是复合语句,顶部有一个条目,底部有一个单独的出口.

结构化块从打开开始,以{结束结束}.该return被包含在这些大括号内,所以这个方案也违背了一个结构化块OpenMP的定义,因为它具有两个出口(一个在return与一个通过在支架的出口)

OpenMP对可以线程化的循环放置以下五个限制:

  • 循环变量必须是有符号整数类型.无符号整数,如DWORD,将无法正常工作.
  • 比较操作必须在形式loop_variable <,<=,>,或>=loop_invariant_integer
  • for循环的第三个表达式或增量部分必须是整数加法或整数减法,并且必须是循环不变值.
  • 如果比较操作是<<=,则循环变量必须在每次迭代时递增,相反,如果比较操作是>>=,则循环变量必须在每次迭代时递减.
  • 循环必须是一个基本块,这意味着除了exit语句之外不允许从循环内部跳转到外部,这将终止整个应用程序.如果使用了goto或break语句,它们必须在循环内跳转,而不是在循环之外.异常处理也是如此; 必须在循环内捕获异常.


Hri*_*iev 6

根据OpenMP标准(第2.5.1节,第40页),for循环控制谓词的可接受形式为:

  • var Relational-op b
  • b关系运算变量

您对的使用j * j <= value明显违反了此要求。其基本原理是,它要求编译器value在运行时发出计算的整数平方根的代码,而对于的某些值value,尤其对于负数,则未定义后者。

您可以将替换j * j <= valuej <= sqrt_value,其中sqrt_value是的整数平方根value,但是这样会出现问题,即在循环内部的结构化块中具有备用退出路径。不幸的是,由于OpenMP不支持并行循环的过早终止,因此在这种情况下不存在简单的解决方案。