性能方面,以下哪项更有效?
在主线程中分配并将值复制到所有线程:
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
初始化变量比将变量复制到所有线程更有效
答案 0 :(得分:4)
您提供的3个版本在性能方面没有太大差异,因为每个版本都使用#pragma omp parallel for
。因此,OpenMP会自动将每个迭代分配给不同的线程。因此,变量i
将变为每个线程的私有,并且每个线程将具有不同的迭代范围以供使用。变量'i'
自动设置为private,以便在更新此变量时避免竞争条件。因为变量'i'
在并行上是私有的,所以不需要在#pragma omp parallel for
上放置 private(i)。
然而,您的第一个版本会产生错误,因为OpenMP期望#pragma omp parallel for
下面的循环具有以下格式:
for(init-expr; test-expr;incr-expr)
为了预先计算工作范围。
for指令对所有结构设置了限制 相关的for循环。具体来说,所有相关的for循环必须 具有以下规范形式:
for(init-expr; test-expr; incr-expr)structured-block(OpenMP Application Program Interface pag.39 / 40。)
编辑:我测试了您的最后两个版本,并检查了生成的程序集。如您所见,两个版本都生成相同的程序集 - &gt; version 2和version 3。