为什么缓冲区应该在64字节边界上对齐以获得最佳性能?

时间:2016-01-18 17:13:24

标签: c++ memory-management latency

this示例程序中,我发现了这个说明:

colnames(df) <- df[2,]

我很感兴趣为什么/* Hardware delivers at most ef_vi_receive_buffer_len() bytes to each * buffer (default 1792), and for best performance buffers should be * aligned on a 64-byte boundary. Also, RX DMA will not cross a 4K * boundary. The I/O address space may be discontiguous at 4K boundaries. * So easiest thing to do is to make buffers always be 2K in size. */ #define PKT_BUF_SIZE 2048 ?为什么,例如2000缓冲区比2048缓冲区慢?我想这就是64位计算机的工作原理 - 由于某种原因,它记忆2048字节比2000字节更快?

为什么确切的2048个缓冲区更快,你可以链接&#34;最小的例子&#34;其中&#34;更大但是64字节对齐&#34;缓冲区更快?

2 个答案:

答案 0 :(得分:11)

在当代架构上,64字节是缓存行的流行大小。从内存中获取的任何内容都会获取整个缓存行。通过将数据与高速缓存行边界对齐,可以最大限度地减少读取数据时需要获取的高速缓存行数,以及写入数据时出现的数据。

当然,您的数据大小也很重要。例如,如果数据的大小除以高速缓存行的大小,那么完全可以仅对齐大小。

相比之下,假设您的数据大96字节。如果对齐32个字节,则最多可以使用三个缓存行:

|............DDDD|DDDDDDDDDDDDDDDD|DDDD............|

相比之下,如果你对齐64个字节(需要另外32个字节的填充),你只需要两个缓存行:

|................|DDDDDDDDDDDDDDDD|DDDDDDDDPPPPPPPP|

D = data,P =填充,每个字符代表4个字节。)

当您同时修改内存时,缓存行更是一个问题。每次弄脏一个缓存行时,所有其他已获取相同缓存行的CPU可能都必须丢弃并重新获取这些缓存行。意外地在同一缓存行上放置不相关的共享数据称为&#34; false sharing&#34;,并且通常使用填充的插入来避免这种情况。

答案 1 :(得分:3)

简短的回答是,大多数现代x64处理器上的数据缓存行是64字节宽,因此CPU每次从主内存执行的提取操作一次只有64个字节。如果您正在加载跨越64字节边界的64字节结构,那么CPU必须获取两个缓存行才能获得整个结构。

真正的答案是这个太复杂的主题无法放入答案框,但Ulrich Drepper's excellent "What Every Programmer Should Know About Memory" paper会给你一个完整的解释。

另请注意,64字节的东西不是计算的基本定律,也不是与64位处理器相关。它恰好是当今大多数工作站中x64处理器上最常见的缓存行大小。其他处理器具有不同的缓存行大小(例如,Xbox360和PS3中使用的Xenon PowerPC具有128字节的缓存行)。