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

Mic*_*hal 8 c++ concurrency multithreading c++11

我想使代码低于并行化:

for(int c=0; c<n; ++c) {
    Work(someArray, c);
}
Run Code Online (Sandbox Code Playgroud)

我这样做了:

#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);
Run Code Online (Sandbox Code Playgroud)

问题是它在英特尔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造成的.

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

Pup*_*ppy 5

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

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


Zag*_*rev 2

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

  • 首先,我会使用 GCC 而不是 VS2012。但是,这里有一些记录选项的链接 http://msdn.microsoft.com/en-us/library/19z1t1wy.aspx 您可以检查 /MT /favor /Gr 等选项 (3认同)