对于大输入,数据位于缓存之外,并且代码受内存限制。
对于小输入,数据位于缓存内(即 L1 / L2 / L3 缓存),并且代码受计算限制。
我假设您在性能测量之前没有尝试刷新缓存。
高速缓存位于 CPU 内部,高速缓存和 ALU(或 SSE)单元之间的带宽非常高(高带宽 - 传输数据的时间更少)。
您的最高级别缓存(即 L3)大小约为 4MB 到 8MB(取决于您的 CPU 型号)。
较大量的数据必须位于 DDR SDRAM 上,即外部 RAM(CPU 外部)。
CPU通过内存总线连接到DDR SDRAM,其带宽比高速缓冲存储器低得多。
Example:
假设您的外部 RAM 类型是双通道 DDR3 SDRAM 1600 https://en.wikipedia.org/wiki/DDR3_SDRAM。
外部RAM和CPU之间的最大理论带宽约为25GB/秒。
将 100MBytes 数据(以 25GB/S 速度)从 RAM 读取到 CPU 大约需要 100e6 / 25e9 = 4 毫秒。
根据我的经验,使用的带宽约为理论带宽的一半,因此读取时间约为8毫秒。
计算时间更短:
假设循环的每次迭代大约需要 2 个 CPU 时钟(仅是一个示例)。
每次迭代处理 16 字节的数据。
处理 100MB 的总 CPU 时钟大约需要 (100e6 / 16)*2 = 12500000 clk。
假设CPU频率为3GHz。
SSE 总处理时间约为 12500000 / 3e9 = 4.2 毫秒。
正如您所看到的,从外部 RAM 读取数据所花费的时间是 SSE 计算时间的两倍。
由于数据传输和计算是并行发生的,因此总时间是 4.2mesc 和 8msec 中的最大值(即 8msec)。
假设不使用 SSE 的循环需要两倍的计算时间,因此不使用 SSE 的计算时间约为 8.4 毫秒。
在上面的示例中,使用 SSE 的总体改进约为 0.4 毫秒。
注意:所选数字仅用于示例目的。
基准:
我对我的系统做了一些基准测试。
我使用的是 Windows 10 和 Visual Studio 2010。
基准测试:对 100MBytes 数据求和(对 25*1024^2 32 位整数求和)。
CPU
- 英特尔酷睿 i5 3550(艾维桥)。
- CPU基础频率为3.3GHz。
- 测试期间的实际核心速度:3.6GHz(启用 Turbo boost)。
- L1数据缓存大小:32KBytes。
- 二级缓存大小:256Bytes(单核二级缓存大小)。
- L3 缓存大小:6MBytes。
记忆:
- 8GB DDR3 双通道。
- RAM频率:666MHz(相当于不带DDR的1333MHz)。
- 内存理论最大带宽:(128*1333/8) / 1024 = 20.8GBytes/Sec。
- 总计 100MB 作为大块with SSE(外部 RAM 中的数据)。
处理时间:6.22毫秒
- 总和 1KB 100 次with SSE(缓存内的数据)。
处理时间:3.86毫秒
- 总计 100MB 作为大块没有上交所(外部 RAM 中的数据)。
处理时间:8.1毫秒
- 总和 1KB 100 次没有上交所(缓存内的数据)。
处理时间:4.73毫秒
已使用内存带宽:100/6.22 =16GB/Sec (数据大小除以时间).
SSE 每次迭代的平均时钟(缓存中的数据):(3.6e9*3.86e-3)/(25/4*1024^2) =2.1 时钟/迭代 (总 CPU 时钟除以迭代次数).