GCC OpenMP并行减少比Visual Studio慢

时间:2015-01-14 23:26:43

标签: c++ performance gcc visual-studio-2013 openmp

我的一位朋友和我在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)上运行时,代码运行大约5秒,而num_threads(1)运行时运行parallel for reduction只有0.5秒。

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

使用Visual Studio 2013,代码几乎可以立即完成。生成的汇编代码可在此处找到:https://gist.github.com/ftfish/f8ffdb9106b82ae63925

我做错了什么?是因为{{1}}的开销吗?为什么Visual Studio表现更好?提前谢谢。

1 个答案:

答案 0 :(得分:1)

如果您的真实代码与此代码一样简单,那么您很可能会失去很多编译器优化的机会。 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

如你所见,绝对没有这里是在运行时计算的,循环完全优化了。因此,程序立即完成。如果你让计算在运行时发生,你显然会增加它。 Here你可以看到添加OMP行实际上会使计算在运行时发生,生成的程序集太长而无法粘贴在这里。

修改

我用g ++和clang ++测试了OMP代码,可以重现你的问题(g ++ ca.0.3s,clang ++ 0.006s,即instant)。 clang确实优化了两个循环,即使使用OMP线也是如此。由于你的代码非常好,这是gcc优化器的错。现在还不清楚gcc的人是否搞砸了,或者他们是否遵循理性的#34;如果用户写OMP,他应该通过测量并发版本更快来找到答案。不要优化它。&#34;我会把钱花在后者身上,但是如果你想确定的话,可以去看看gcc bugzilla。

我在评论中提到的结论仍然是什么:衡量一切。

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

最后一句话:

如果您的真实代码是像这里的双循环,请考虑平行化最外层的代码来节省昂贵的OMP启动程序(但是测量(!),这当然可能没有帮助。)