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

C++ 为什么缓冲区应该在64字节边界上对齐以获得最佳性能?,c++,memory-management,latency,C++,Memory Management,Latency,在示例程序中,我发现了以下注释: /* 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 addr

在示例程序中,我发现了以下注释:

/* 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
我很感兴趣的是,为什么为了获得最佳性能,缓冲区应该在64字节边界上对齐?例如,为什么2000个缓冲区比2048个缓冲区慢?我猜这就是64位计算机的工作原理——由于某种原因,它存储2048字节比存储2000字节要快


为什么2048个缓冲区的速度更快?您可以链接“最小示例”,其中“更大但64字节对齐”的缓冲区更快?

64字节是当代体系结构中常用的缓存线大小。从内存中进行的任何提取都会提取整个缓存线。通过将数据与缓存线边界对齐,可以最大限度地减少读取数据所需的缓存线数量,以及写入数据时被弄脏的缓存线数量

当然,数据的大小也很重要。例如,如果数据的大小除以缓存线的大小,则只在大小上对齐是完全正确的

相反,假设您的数据是96字节大。如果按32字节对齐,最多可以使用三条缓存线:

|............DDDD|DDDDDDDDDDDDDDDD|DDDD............|
|................|DDDDDDDDDDDDDDDD|DDDDDDDDPPPPPPPP|
相比之下,如果按64字节对齐(需要另外32字节的填充),则只需要两条缓存线:

|............DDDD|DDDDDDDDDDDDDDDD|DDDD............|
|................|DDDDDDDDDDDDDDDD|DDDDDDDDPPPPPPPP|
D
=数据,
p
=填充,每个字符代表4个字节。)


当您同时修改内存时,缓存线更值得关注。每次弄脏一条缓存线时,获取同一缓存线的所有其他CPU都可能必须丢弃并重新蚀刻这些缓存线。意外地将不相关的共享数据放在同一缓存线上被称为“虚假共享”,通常使用插入填充来避免这种情况。

简单的回答是,大多数当代x64处理器上的数据缓存线都是64字节宽,因此CPU从主内存执行的每次提取都是64字节。如果要加载跨越64字节边界的64字节结构,那么CPU必须获取两条缓存线才能获取整个结构

真正的答案是,这个主题太复杂,无法放入答案框,但会给你一个完整的解释


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

您认为“64位”与“64字节”有关系吗?@KerrekSB ok,也许我的猜测是错误的,那么你能提供一个如何在代码中实现这一点的实际例子吗?@Dave:可以是一些简单的事情,比如在类定义中添加显式的“填充”(例如字符数组),或者使用
alignas
。。。