根据我的理解,在所有版本的openmp中,这些都是正确的:
//int i declared in loop, explicitly private
#pragma omp parallel for
for (int i = 0; i < NUMEL; i++)
{
foo(i);
}
//int i declared outsize loop, but is the iterated value, implicitly private
int i;
#pragma omp parallel for
for (i = 0; i < NUMEL; i++)
{
foo(i);
}
然而,我更常见的是第二个而不是第一个。那是为什么?
答案 0 :(得分:4)
因为不是每个人都用C ++编写或者是针对C99兼容的C编译器。有些人更喜欢坚持在块的开头声明变量的旧C要求,以便代码与旧的(C99之前的)C编译器更兼容。
答案 1 :(得分:2)
在循环外声明循环迭代器容易出错,通常是不必要的。关于OpenMP的SO问题中最大的部分可能是由于内部循环和在循环之外声明迭代器而引起的问题。
int i,j;
#pragma omp parallel for
for(i=0; i<n; i++) { //OpenMP makes the parallel index private by default
for( j=0; j<n; j++) { //error j should be private but is shared by default
如果使用循环初始声明,则不会发生此类错误
#pragma omp parallel for
for(int i=0; i<n; i++) { //i is private
for(int j=0; j<n; j++) {// j is private now
不幸的是,GCC和ICC默认使用的C语言GNU89 does not allow loop initial declarations(即使它确实允许混合声明)因此循环初始声明需要C99(例如GNU99)方言或C ++。
但是,有时在需要最后一个迭代器时在循环外声明迭代器是有用的。在这种情况下,应使用lastprivate
。例如,如果我只想循环遍历四个元素中的多个,然后知道有多少最终元素可供使用,我可以这样做:
#include <stdio.h>
int main() {
int i,j;
int n,m;
n = 10;
m = 25;
#pragma omp parallel for lastprivate(i,j)
for(i=0; i<(n & -4); i++) {
for(j=0; j<(m & -4); j++) {
}
}
printf("%d %d\n",i, j); //output 8, 24
}
答案 2 :(得分:0)
程序员曾告诉我他更喜欢第二个版本,因为在循环退出后你可以在调试器中看到i
的值,这对于复杂条件或breaks
的循环很有用。但是这些循环不会很好地并行化,所以如果这是OpenMP示例的原因我会感到惊讶。