在性能方面,以下哪个更有效?

分配主线程并将值复制到所有线程:

int i = 0;
#pragma omp parallel for firstprivate(i)
for( ; i < n; i++){
    ...
}

在每个线程中声明和分配变量
#pragma omp parallel for
for(int i = 0; i < n; i++){
    ...
}

在主线程中声明变量,但在每个线程中分配它。
int i;
#pragma omp parallel for private(i)
for(i = 0; i < n; i++){
    ...
}

这似乎是一个愚蠢的问题,并且/或者对性能的影响可以忽略不计。但是我正在并行化一个执行少量计算并且被调用很多次的循环,因此我可以从该循环中挤出的任何优化都是有帮助的。

我正在寻找一个更底层的解释以及OpenMP如何处理此问题。

例如,如果并行处理大量线程,则我认为第二种实现会更高效,因为使用xor初始化变量比将变量复制到所有线程要有效得多。

最佳答案

在您介绍的3个版本之间,在性能方面并没有太大差异,因为每个版本都使用#pragma omp parallel for。因此,OpenMP将自动将每个迭代分配给不同的线程。因此,变量i将变为每个线程专用,并且每个线程将具有不同的for迭代范围。变量'i'会自动设置为private,以避免在更新此变量时出现争用情况。由于变量'i'无论如何都将是并行的,因此无需将 private(i)放在#pragma omp parallel for上。

不过,您的第一个版本会产生错误,因为OpenMP期望#pragma omp parallel for下面的循环具有以下格式:
for(init-expr; test-expr;incr-expr)
为了预先计算工作范围。



编辑:我测试了您的最后两个版本,并检查了生成的程序集。两种版本都产生相同的程序集,如您所见-> version 2version 3

09-30 18:16
查看更多