英特尔的多线程比 AMD 慢得多
Multithreading on Intel much slower than on AMD
我想使下面的代码并行化:
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的缓存之间始终同步,它甚至可能导致运行速度变慢,然后以单线程方式运行。
- 在C++中使用cURL和多线程
- 多线程双缓冲区
- 为什么我的多线程作业队列崩溃
- 在main()之外初始化std::vector会导致性能下降(多线程)
- 试图创建一个多线程程序来查找0-100000000之间的总素数
- 为什么一个向量上的多线程操作很慢
- 学习多线程C++:添加线程不会使执行速度更快,即使它看起来应该
- 全局变量 多读取器 一个写入器多线程安全?
- boost::文件系统::recursive_directory_iterator多线程安全
- 如何阻止TensorFlow的多线程
- 如何在多线程中正确使用unique_ptr进行多态性?
- 并发/多线程:是否可以以这种方式生成相同的输出?
- sigwait() 在多线程程序中不起作用
- 多线程程序中出现意外的内存泄漏
- 静态 constexpr 类成员变量对多线程读取是否安全?
- 多线程比没有线程C++慢
- 具有 C++11 多线程的特征库
- 通过安装信号处理程序关闭多线程应用程序
- 成员变量在多线程 C++ 时自行更改
- 英特尔的多线程比 AMD 慢得多