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

Multithreading on Intel much slower than on AMD

本文关键字:AMD 多线程 英特尔      更新时间:2023-10-16

我想使下面的代码并行化:

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%。我在三个英特尔CPU(Nehalem 2core+HT,Sandy Bridge 2core+HT,Ivy Brigde 4core+HT)上运行它。AMD处理器是Phenom II x2,解锁了4个内核。在 2 核英特尔处理器上,使用 50 个线程的运行速度提高了 4%。在 4 核上,它在 4 个线程上的运行速度也提高了 50%。 我正在使用VS2012,Windows 7进行测试。

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

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

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

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

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

你也应该对CPU缓存感到敬畏。这是一篇关于这个主题的好文章。

简短版本:硬件缓存数据,但如果您在同一内存(SomeArray)上工作,它必须在CPU的缓存之间始终同步,它甚至可能导致运行速度变慢,然后以单线程方式运行。