____cacheline_aligned_in_smp用于linux中的结构

K_K*_*K_K 5 smp linux-kernel

为什么在Linux中很多结构使用____cacheline_aligned_in_smp宏?在访问结构时是否有助于提高性能.如果是,那怎么样?

小智 6

任何缓存(dcache 或 icache)中的每个缓存行都是 64 字节(在 x86 中)架构。需要缓存对齐以避免缓存行的错误共享。如果缓存行在全局变量之间共享(在内核中更常见)如果全局变量之一被其缓存中的处理器之一更改,则它将将该缓存行标记为脏。在剩余的 CPU 缓存行中,它成为陈旧条目,需要刷新并从内存中重新获取。这可能会导致缓存行未命中,从而需要更多的 CPU 周期。这会降低系统的性能。请记住,这是针对全局变量的。大多数内核数据结构器使用它来避免缓存行丢失。


kav*_*ias 5

____cacheline_aligned指示编译器针对特定体系结构在与L1高速缓存行的开头对应的地址处实例化结构或变量,即,使其与L1高速缓存行对齐。____cacheline_aligned_in_smp相似,但是实际上只有在以SMP配置编译内核(即,使用option CONFIG_SMP)时,L1缓存行才会对齐。这些定义在文件include / linux / cache.h中

这些定义对于不是通过某些分配器动态分配的变量(和数据结构)很有用,但是它们是全局的,由编译器分配的变量(通过可以按特定对齐方式分配内存的动态内存分配器可以实现类似的效果)。

高速缓存行对齐的变量的原因是在SMP系统中通过硬件高速缓存一致性机制来管理这些变量的高速缓存到高速缓存的传输,以便在移动其他变量时不会隐式地发生它们的移动。这是针对性能至关重要的代码,在该代码中,人们期望多个cpus(核心)对变量的访问产生竞争。在这种情况下,人们通常希望避免的问题是错误共享。

从高速缓存行的开头开始的变量内存就达到了此目的的一半。还需要“打包” 应一起移动的变量。一个示例是变量数组,其中数组的每个元素只能由一个cpu(核心)访问:

struct my_data {
   long int a;
   int b;
} ____cacheline_aligned_in_smp cpu_data[ NR_CPUS ];
Run Code Online (Sandbox Code Playgroud)

这种定义将要求编译器(在内核的SMP配置中)每个cpu的结构都将从缓存行边界开始。编译器将隐式地在每个cpu的结构之后分配额外的空间,以便下一个cpu的结构也将从缓存行边界开始。

另一种选择是用缓存行的伪未使用字节大小填充数据结构:

struct my_data {
   long int a;
   int b;
   char dummy[L1_CACHE_BYTES];
} cpu_data[ NR_CPUS ];
Run Code Online (Sandbox Code Playgroud)

在这种情况下,由于缓存容量未命中,只有虚拟的,未使用的数据将被无意移动,而每个cpu实际访问的数据只会从缓存移至内存,反之亦然。