我们有一个简单的内存吞吐量基准。它所做的只是对一大块内存重复进行memcpy。
查看几台不同机器上的结果(针对 64 位编译),Skylake 机器的表现明显优于 Broadwell-E,操作系统 (Win10-64)、处理器速度和 RAM 速度 (DDR4-2133) 保持相同。我们不是在谈论几个百分点,而是大约 2 的因数。 Skylake 配置为双通道,Broadwell-E 的结果对于双通道/三通道/四通道没有变化。
任何想法为什么会发生这种情况?以下代码在 VS2015 的 Release 中编译,并报告完成每个 memcpy 的平均时间:
64 位:Skylake 为 2.2 毫秒,而 Broadwell-E 为 4.5 毫秒
32 位:Skylake 为 2.2 毫秒,而 Broadwell-E 为 3.5 毫秒.
我们可以通过利用多个线程在四通道 Broadwell-E 构建上获得更大的内存吞吐量,这很好,但看到单线程内存访问的如此巨大差异令人沮丧。对于为什么差异如此明显有什么想法吗?
我们还使用了各种基准测试软件,它们验证了这个简单示例所显示的内容 - Skylake 上的单线程内存吞吐量要好得多。
#include <memory>
#include <Windows.h>
#include <iostream>
//Prevent the memcpy from being optimized out of the for loop
_declspec(noinline) void MemoryCopy(void *destinationMemoryBlock, void *sourceMemoryBlock, size_t size)
{
memcpy(destinationMemoryBlock, sourceMemoryBlock, size);
}
int main()
{
const int SIZE_OF_BLOCKS = 25000000;
const int NUMBER_ITERATIONS = 100;
void* sourceMemoryBlock = malloc(SIZE_OF_BLOCKS);
void* destinationMemoryBlock = malloc(SIZE_OF_BLOCKS);
LARGE_INTEGER Frequency;
QueryPerformanceFrequency(&Frequency);
while (true)
{
LONGLONG total = 0;
LONGLONG max = 0;
LARGE_INTEGER StartingTime, EndingTime, ElapsedMicroseconds;
for (int i = 0; i < NUMBER_ITERATIONS; ++i)
{
QueryPerformanceCounter(&StartingTime);
MemoryCopy(destinationMemoryBlock, sourceMemoryBlock, SIZE_OF_BLOCKS);
QueryPerformanceCounter(&EndingTime);
ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - StartingTime.QuadPart;
ElapsedMicroseconds.QuadPart *= 1000000;
ElapsedMicroseconds.QuadPart /= Frequency.QuadPart;
total += ElapsedMicroseconds.QuadPart;
max = max(ElapsedMicroseconds.QuadPart, max);
}
std::cout << "Average is " << total*1.0 / NUMBER_ITERATIONS / 1000.0 << "ms" << std::endl;
std::cout << "Max is " << max / 1000.0 << "ms" << std::endl;
}
getchar();
}