10

我正在创建一个基于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 出错,说明invalid controlling predicate与 for 循环有关。

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

4

2 回答 2

14

return不允许在循环内,因为它会导致在花括号之前退出。

请注意下面给出的定义:

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

结构化块 - 对于 C/C++,一个可执行语句,可能是复合语句,顶部有一个入口,底部有一个出口。

结构化块以 open 开始,以{close 结束}。包含在这些return大括号中,因此该程序也违反了结构化块的 OpenMP 定义,因为它有两个出口(一个在return大括号的出口处,一个在通过大括号的出口处)

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

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

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

  • var 关系运算 b
  • b 关系运算变量

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

您可以替换j * j <= valuej <= sqrt_value,其中sqrt_value是 的整数平方根value,但是在循环内的结构化块中有替代退出路径会出现问题。不幸的是,在这种情况下不存在简单的解决方案,因为 OpenMP 不支持提前终止并行循环。

于 2013-07-10T16:40:53.693 回答