GCC OpenMP并行处理比Visual Studio减少速度更慢

问题描述 投票:0回答:1

我的一个朋友和我在GCC中遇到有关parallel for reduction的性能问题。

代码:

#include <cstdio>

int main() {
    int tans = 0;
    for (int i = 0; i < 100000; ++i)
        #pragma omp parallel for reduction(+:tans)
        for (int id = 0; id < 10000; ++id) {
            tans++;
        }
    printf("%d\n", tans);
}

(此无用的代码仅用于演示问题)

[当使用GCC(版本4.9.2(tdm64-1)编译)并在我的4核8线程系统(Win 8.1 64b)上运行时,代码运行大约5s,而对于num_threads(1),它仅运行0.5s 。

我还在24核系统(gcc版本4.8.2(Ubuntu 4.8.2-19ubuntu1))上尝试过相同的代码,并行版本仍然非常慢,运行时间非常不稳定,范围为1s到10秒。

对于Visual Studio 2013,代码总是几乎立即完成。生成的汇编代码可以在这里找到:https://gist.github.com/ftfish/f8ffdb9106b82ae63925

我做错了什么?是因为parallel for reduction的开销吗?为什么Visual Studio的性能更好?预先谢谢你。

c++ performance gcc visual-studio-2013 openmp
1个回答
2
投票

如果您的真实代码与此代码一样简单,则很可能会损失很多编译器优化的机会。 g++ -O3为您发布的代码减去OMP行生成以下程序集:

.cfi_startproc
subq    $8, %rsp
.cfi_def_cfa_offset 16
movl    $1000000000, %esi
movl    $.LC0, %edi
xorl    %eax, %eax
call    printf
xorl    %eax, %eax
addq    $8, %rsp
.cfi_def_cfa_offset 8
ret

正如您所看到的,这里的nothing绝对是在运行时计算的,both循环已被完全优化。这样,程序立即完成。如果让计算在运行时进行,显然会增加它。 Here您会看到添加OMP行实际上使计算在运行时发生,生成的程序集太长而无法粘贴到此处。

编辑:

我用g ++和clang ++都测试了OMP代码,可以重现您的问题(g ++大约0.3s,clang ++ 0.006s,即即刻)。 clang确实优化了两个循环,即使使用OMP线也是如此。由于您的代码非常完美,因此这是gcc优化器的错误。现在还不清楚gcc伙计们是否搞砸了,或者是否遵循了诸如“如果用户编写OMP,他们应该通过测量并行版本更快而发现。不要对其进行优化”之类的合理性。我会把钱花在后者上,但是如果您想确保的话,请访问gcc bugzilla。

剩下的是我在评论中提到的结论:衡量一切。

在这种特殊情况下:如果要定位gcc和VC,只需在两种环境中同时测量两个变体,然后将更好的变体交付给客户。如果您认为这是gcc性能错误,仍然可以为他们编写错误报告。

最后一句话:

如果您的实际代码是像这样的双循环,请考虑并行处理最外部的代码,以节省昂贵的OMP启动过程(但是,measure(!),这当然可能无济于事。)

© www.soinside.com 2019 - 2024. All rights reserved.