OpenMP 性能影响:私有指令与在构造内部声明变量

Posted

技术标签:

【中文标题】OpenMP 性能影响:私有指令与在构造内部声明变量【英文标题】:OpenMP Performance impact: private directive vs. declaring variable inside for construct 【发布时间】:2013-03-18 01:18:01 【问题描述】:

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

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

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 初始化变量比将变量复制到所有线程要高效得多

【问题讨论】:

您是否尝试过测量,还是要求我们为您测量? 我没有测量它,但我不寻求数字的答案,我寻求更底层的答案。 如果您尝试测量它然后要求解释结果,这个问题会更有趣。 第一个版本不是有效的 OpenMP 代码。其他两个版本是等效的,很可能会导致为提取的 OpenMP 区域生成相同的汇编代码。 【参考方案1】:

您提供的 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 Application Program Interface pag. 39/40.)

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

【讨论】:

以上是关于OpenMP 性能影响:私有指令与在构造内部声明变量的主要内容,如果未能解决你的问题,请参考以下文章

内部类中的私有构造函数在外部类中初始化

TypeScript构造函数中的私有变量声明以引发DI

内部类

内部类中有两个声明的构造函数

OpenMP基本概念转

OpenMP 导致内部编译器错误