为了防止错误共享,我想将数组的每个元素与缓存行对齐。因此,首先我需要知道缓存行的大小,因此我为每个元素分配相应的字节数。其次,我希望数组的开头与缓存行对齐。
我使用的是Linux和8核x86平台。首先,如何找到缓存行大小。其次,如何与 C 中的缓存行对齐。我正在使用 gcc 编译器。
因此,结构如下,假设缓存行大小为 64。
element[0] occupies bytes 0-63
element[1] occupies bytes 64-127
element[2] occupies bytes 128-191
等等,当然假设 0-63 与缓存行对齐。
我使用的是Linux和8核x86平台。首先如何找到缓存行大小。
$ getconf LEVEL1_DCACHE_LINESIZE
64
将值作为宏定义传递给编译器。
$ gcc -DLEVEL1_DCACHE_LINESIZE=`getconf LEVEL1_DCACHE_LINESIZE` ...
在运行时
sysconf(_SC_LEVEL1_DCACHE_LINESIZE)
可用于获取 L1 缓存大小。
要了解尺寸,您需要使用处理器的文档进行查找,据我所知,没有编程方法可以做到这一点。然而,从好的方面来说,大多数缓存行都是基于英特尔标准的标准大小。在 x86 上,缓存行为 64 字节,但是,为了防止错误共享,您需要遵循目标处理器的指导原则(英特尔对其基于 netburst 的处理器有一些特殊说明),通常您需要为此对齐到 64 字节(英特尔指出您还应该避免跨越 16 字节边界)。
要在 C 或 C++ 中执行此操作,需要使用标准
aligned_alloc
函数或编译器特定说明符之一,例如 __attribute__((aligned(64)))
或 __declspec(align(64))
。要在结构中的成员之间填充以将它们拆分到不同的缓存行,您需要插入一个足够大的成员以将其与下一个 64 字节边界对齐
另一种简单的方法是只获取 /proc/cpuinfo:
grep cache_alignment /proc/cpuinfo
没有完全可移植的方法来获取缓存行大小。但如果您使用的是 x86/64,则可以调用
cpuid
指令来获取您需要了解的有关缓存的所有信息 - 包括大小、缓存行大小、多少级等...
http://softpixel.com/~cwright/programming/simd/cpuid.php
(向下滚动一点,该页面是关于 SIMD 的,但其中有一个部分获取缓存行。)
至于对齐数据结构,也没有完全可移植的方法来做到这一点。 GCC 和 VS10 有不同的方法来指定结构的对齐方式。 “破解”它的一种方法是用未使用的变量填充结构,直到它与您想要的对齐方式匹配。
为了对齐你的 malloc(),所有主流编译器也为此目的对齐了 malloc 函数。
posix_memalign 或 valloc 可用于将分配的内存与缓存行对齐。