3

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

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

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比将变量复制到所有线程更有效

4

1 回答 1

4

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

然而,您的第一个版本会产生错误,因为 OpenMP 期望下面的循环#pragma omp parallel for具有以下格式:

for(init-expr; test-expr;incr-expr)

为了预先计算工作范围。

for 指令对所有相关 for 循环的结构进行了限制。具体来说,所有关联的 for 循环必须具有以下规范形式:

for (init-expr; test-expr;incr-expr) 结构化块(OpenMP 应用程序接口第 39/40 页。)

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

于 2013-03-18T01:25:15.673 回答