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

时间:2013-07-10 15:52:46

标签: c openmp

我正在创建基于C - determine if a number is prime的基本素数检查器,但使用的是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平方引起的。有没有办法解决这个问题,仍然可以从算法中获得所需的输出?

2 个答案:

答案 0 :(得分:12)

循环中不允许使用

return,因为它会在大括号之前导致退出。

请注意以下定义:

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

  

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

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

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

  • 循环变量必须是有符号整数类型。无符号整数, 如DWORD的,将无法正常工作。
  • 比较操作必须采用loop_variable <<=>的形式, 或>= loop_invariant_integer
  • for循环的第三个表达式或增量部分必须是 整数加法或整数减法和循环 不变的价值。
  • 如果比较操作是<<=,则循环变量必须 每次迭代都会递增,反之,如果进行比较 操作是>>=,循环变量必须减少每一个 迭代。
  • 循环必须是一个基本块,意味着没有从内部跳转 除了退出之外,允许循环到外部 声明,终止整个应用程序。如果是陈述 使用goto或break,它们必须在循环内跳转,而不是在外面 它。异常处理也是如此;必须抓住例外 在循环中。

答案 1 :(得分:4)

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

  • var relational-op b
  • b relational-op var

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

您可以将j * j <= value替换为j <= sqrt_value,其中sqrt_valuevalue的整数平方根,但是会出现问题,因为在{{1}}中有另一个退出路径循环内部的结构化块。遗憾的是,在这种情况下不存在简单的解决方案,因为OpenMP不支持过早终止并行循环。