英特尔的多线程比AMD慢多了

时间:2012-12-12 19:49:36

标签: c++ multithreading concurrency c++11

我想将代码编写为并行化:

for(int c=0; c<n; ++c) {
    Work(someArray, c);
}

我这样做了:

#include <thread>
#include <vector>

auto iterationsPerCore = n/numCPU;
std::vector<std::future<void>> futures;

for(auto th = 0; th < numCPU; ++th) {
    for(auto n = th * iterationsPerCore; n < (th+1) * iterationsPerCore; ++n) {
        auto ftr = std::async( std::launch::deferred | std::launch::async,
            [n, iterationsPerCore, someArray]()
            {
                for(auto m = n; m < n + iterationsPerCore; ++m)
                    Work(someArray, m);
            }
        );
        futures.push_back(std::move(ftr));
    }

    for(auto& ftr : futures)
        ftr.wait();
}

// rest of iterations: n%iterationsPerCore
for(auto r = numCPU * iterationsPerCore; r < n; ++r)
    Work(someArray, r);

问题是它在英特尔CPU上的运行速度只有 50%,而在AMD上运行速度 300%更快。 我在三个Intel CPU(Nehalem 2core + HT,Sandy Bridge 2core + HT,Ivy Brigde 4core + HT)上运行它。 AMD处理器是Phenom II x2,解锁4核。在2核英特尔处理器上,4线程运行速度提高50%。在4核上,它在4个线程上运行速度提高了50%。我正在使用VS2012,Windows 7进行测试。

当我尝试使用8个线程时,它比英特尔上的串行环路慢8倍。我想这是由HT引起的。

你怎么看?这种行为的原因是什么?也许代码不正确?

3 个答案:

答案 0 :(得分:5)

我怀疑虚假分享。当两个变量共享同一个缓存行时会发生这种情况。实际上,它们上的所有操作必须非常昂贵地同步即使它们不是同时访问的,因为缓存只能在特定大小的缓存行中运行,即使您的操作更精细-grained。我怀疑AMD硬件更具弹性或者有不同的硬件设计来应对这种情况。

要进行测试,请更改代码,以便每个内核仅适用于64字节倍数的块。这应该避免任何缓存行共享,因为Intel CPU只有64字节的缓存行。

答案 1 :(得分:2)

我想说你需要改变你的编译器设置,使所有编译的代码最小化分支数量。两种不同的CPU样式具有不同的操作前瞻设置。您需要更改编译器优化设置以匹配目标 CPU,而不是编译代码的CPU。

答案 2 :(得分:2)

你也应该是cpu缓存的一部分。 Here是关于此主题的好文章。

简短版本:hw缓存数据,但是如果你正在处理相同的内存(SomeArray),它必须在cpus的缓存之间一直同步,它甚至可能导致运行速度慢于单个内存线程方式。