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