用户空间消除缓存行伪共享的方法
创始人
2025-07-09 17:41:07
0

2个处理器写到不同的物理地址,但是2个物理地址映射到同一个缓存行,这种情况称为缓存行伪共享(False Sharing),造成的危害是:因为缓存一致性协议而生成大量通信,导致性能下降。消除缓存行伪共享的方法是把不相关的2个数据放在不同的缓存行。

可以使用GCC编译器提供的属性“aligned”修饰结构体的字段、结构体或者变量。可以选择指定名称前后带有“__”(2个下划线)的属性名称,在头文件中使用它们,不必担心可能有名称相同的宏,例如使用属性名称“aligned”取代“aligned”。

为了使用方便,自己定义宏__cacheline_aligned如下。目前主流的处理器缓存的行大小是64字节,所以把宏L1_CACHE_LINE_SIZE的默认值设置为64。

#if !defined(L1_CACHE_LINE_SIZE)
#define L1_CACHE_LINE_SIZE  64
#endif

#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_LINE_SIZE)))

#define __cacheline_aligned attribute((aligned(L1_CACHE_LINE_SIZE))) 可以使用宏__cacheline_aligned修饰结构体的字段,确保这个字段在结构体里面的偏移对齐到一级缓存行的长度,也就是偏移是一级缓存行的长度的整数倍。

可以使用宏__cacheline_aligned修饰结构体,确保这个结构体的长度对齐到一级缓存行的长度,并且类型是这个结构体的变量(包括全局变量和局部变量)的地址对齐到一级缓存行的长度。

可以使用宏__cacheline_aligned修饰变量,确保变量的地址对齐到一级缓存行的长度。

1.动态分配结构体

例如结构体s定义如下,要把字段m1和m2分别放在2个缓存行中,使用宏__cacheline_aligned修饰字段m2可以确保这个字段在结构体里面的偏移对齐到一级缓存行的长度,使用宏__cacheline_aligned修饰结构体可以确保结构体的长度对齐到一级缓存行的长度。要想使得字段m2的地址是一级缓存行的长度的整数倍,必须确保动态分配的结构体的起始地址是一级缓存行的长度的整数倍,并且字段m2在结构体里面的偏移是一级缓存行的长度的整数倍。

struct s {
 int m1;
 int m2 __cacheline_aligned;
} __cacheline_aligned;

可以使用函数posix_memalign()或aligned_alloc()给结构体动态分配内存,这两个函数的原型如下。

#include 

int posix_memalign(void **memptr, size_t alignment, size_t size);
void *aligned_alloc(size_t alignment, size_t size);

int posix_memalign(void **memptr, size_t alignment, size_t size); void aligned_alloc(size_t alignment, size_t size); 函数 posix_memalign()分配size字节的内存,把分配的内存的地址存放在memptr中。分配的内存的地址是参数alignment的整数倍,参数alignment必须是2的幂,并且是sizeof(void *)的整数倍。

函数aligned_alloc()是C11标准定义的函数,参数size必须是参数alignment的整数倍。分配的内存的地址是参数alignment的整数倍,参数alignment必须是2的幂,并且是sizeof(void *)的整数倍。函数aligned_alloc()返回分配的内存的地址。

2.静态分配结构体

如果使用宏__cacheline_aligned修饰结构体,那么这个结构体的长度是一级缓存行的长度的整数倍,并且类型是这个结构体的变量(包括全局变量和局部变量)的地址是一级缓存行的长度的整数倍。下面是一个例子。

#include 

#if !defined(L1_CACHE_LINE_SIZE)
#define L1_CACHE_LINE_SIZE  64
#endif

#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_LINE_SIZE)))

struct s {
 int m1;
 int m2 __cacheline_aligned;
} __cacheline_aligned;

struct s g;

int main(int argc, char *argv[])
{
    struct s v;

    printf("sizeof(g)=%lu, &g=%p, &g %% L1_CACHE_LINE_SIZE = %lu\n",
        sizeof(g), &g, (((unsigned long)&g) % L1_CACHE_LINE_SIZE));
    
    printf("sizeof(v)=%lu, &v=%p, &v %% L1_CACHE_LINE_SIZE = %lu\n",
        sizeof(v), &v, (((unsigned long)&v) % L1_CACHE_LINE_SIZE));
    return 0;
}

运行程序,从打印的信息可以看到:g和v的长度都是128字节,地址是64的整数倍。

如果使用宏__cacheline_aligned修饰变量,那么变量的地址是一级缓存行的长度的整数倍,变量的长度不一定是一级缓存行的长度的整数倍。下面是一个例子。

#include 

#if !defined(L1_CACHE_LINE_SIZE)
#define L1_CACHE_LINE_SIZE  64
#endif

#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_LINE_SIZE)))

struct s {
 int m1;
 int m2;
};

struct s g __cacheline_aligned;

int main(int argc, char *argv[])
{
    struct s v __cacheline_aligned;

    printf("sizeof(g)=%lu, &g=%p, &g %% L1_CACHE_LINE_SIZE = %lu\n",
        sizeof(g), &g, (((unsigned long)&g) % L1_CACHE_LINE_SIZE));
    
    printf("sizeof(v)=%lu, &v=%p, &v %% L1_CACHE_LINE_SIZE = %lu\n",
        sizeof(v), &v, (((unsigned long)&v) % L1_CACHE_LINE_SIZE));
    return 0;
}

运行程序,从打印的信息可以看到:g和v的长度都是8字节,地址是64的整数倍。

3.参考文档

(1) GCC的公共函数属性aligned,https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-aligned-function-attribute

(2) GCC的公共变量属性aligned,https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-aligned-variable-attribute

(3) GCC的公共类型属性aligned,https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-aligned-type-attribute

(4) posix_memalign, https://man7.org/linux/man-pages/man3/posix_memalign.3.html

相关内容

热门资讯

PHP新手之PHP入门 PHP是一种易于学习和使用的服务器端脚本语言。只需要很少的编程知识你就能使用PHP建立一个真正交互的...
网络中立的未来 网络中立性是什... 《牛津词典》中对“网络中立”的解释是“电信运营商应秉持的一种原则,即不考虑来源地提供所有内容和应用的...
各种千兆交换机的数据接口类型详... 千兆交换机有很多值得学习的地方,这里我们主要介绍各种千兆交换机的数据接口类型,作为局域网的主要连接设...
什么是大数据安全 什么是大数据... 在《为什么需要大数据安全分析》一文中,我们已经阐述了一个重要观点,即:安全要素信息呈现出大数据的特征...
如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
P2P的自白|我不生产内容,我... 现在一提起P2P,人们就会联想到正在被有关部门“围剿”的互联网理财服务。×租宝事件使得劳...
Intel将Moblin社区控... 本周二,非营利机构Linux基金会宣布,他们将担负起Moblin社区的管理工作,而这之前,Mobli...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...