我正在尝试编译以下代码:
#pragma omp parallel shared (j)
{
#pragma omp for schedule(dynamic)
for(i = 0; i != j; i++)
{
// do something
}
}
但是我得到了以下错误:错误:无效的控制谓词。
OpenMP standard声明对于parallel for
构造函数,它“只”允许以下运算符之一:<
、<=
、>
>=
。
我不明白为什么不允许使用i != j
。对于static schedule
,我可以理解,因为编译器需要预先计算分配给每个线程的迭代次数。但是我不能理解为什么在这种情况下会有这样的限制。有什么线索吗?
编辑:即使我创建了for(i = 0; i != 100; i++)
,也可以使用,尽管我可以只使用"<“或"<=”。
发布于 2012-11-16 02:14:15
。
我就这个问题给OpenMP开发人员发了一封电子邮件,得到的答案是:
对于带符号的int,换行行为是未定义的。如果我们允许!=
,程序员可能会得到意想不到的tripcount。问题是编译器是否可以生成代码来计算循环的trip计数。
对于一个简单的循环,例如:
for( i = 0; i < n; ++i )
编译器可以确定有'n‘次迭代,如果是n>=0,则为,如果n< 0,则为零迭代。
对于像这样的循环:
for( i = 0; i != n; ++i )
同样,编译器应该能够确定有'n‘次迭代,如果n<0,,;如果n<0,,我们不知道它有多少次迭代。
对于像这样的循环:
for( i = 0; i < n; i += 2 )
编译器可以生成代码来计算跳跃计数(循环迭代计数),如果n >= 0,则为floor((n+1)/2),如果n< 0,则计算0。
对于像这样的循环:
for( i = 0; i != n; i += 2 )
编译器无法确定'i‘是否会命中'n’。如果“n”是奇数怎么办?
对于像这样的循环:
for( i = 0; i < n; i += k )
编译器可以生成代码来计算floor((n+k-1)/k) if n >= 0和0 if n< 0,因为编译器知道循环必须向上计数;在这种情况下,如果k < 0,则它不是合法的OpenMP程序。
对于像这样的循环:
for( i = 0; i != n; i += k )
编译器甚至不知道我是在向上还是向下计数。它不知道'i‘是否会命中'n’。它可能是一个无限循环。
Credits:OpenMP ARB
发布于 2012-11-16 01:25:15
答案很简单。OpenMP不允许提前终止线程组。使用==或!=时,OpenMP无法确定循环何时停止。1.一个或多个线程可能会遇到终止条件,该条件可能不是唯一的。2. OpenMP没有办法关闭其他可能永远不会检测到这种情况的线程。
发布于 2012-11-10 02:10:03
如果我看到这份声明
for(i = 0; i != j; i++)
用来代替语句
for(i = 0; i < j; i++)
我会想知道为什么程序员会做出这样的选择,更不用说它可能意味着同样的事情。这可能是因为OpenMP在语法上做出了艰难的选择,以迫使代码具有一定的清晰度。
这里的代码对!=
的使用提出了挑战,并可能有助于解释为什么它是不允许的。
#include <cstdio>
int main(){
int j=10;
#pragma omp parallel for
for(int i = 0; i < j; i++){
printf("%d\n",i++);
}
}
请注意,在for
语句和循环本身中,i
都是递增的,这导致了无限循环的可能性(但不是保证)。
如果谓词为<
,那么在并行上下文中仍然可以很好地定义循环的行为,而无需编译器在循环中检查i
的更改并确定这些更改将如何影响循环的界限。
如果谓词为!=
,则循环的行为不再是定义良好的,它的范围可能是无限的,从而防止了简单的并行细分。
https://stackoverflow.com/questions/13312679
复制相似问题