C++中的错误共享

False sharing in C++

本文关键字:共享 错误 C++      更新时间:2023-10-16

我有几个类受到缓存争用的影响,并使用"new"运算符进行分配。我能以某种方式确保"new"返回一个与缓存行对齐的地址吗?

我正在使用GCC(如果不可能移植的话)。

您可以将memalign_aligned_alloc分别用于glibc或windows CRT系统。您甚至可以使用像nedmalloc这样的自定义分配器,并让它对齐块,这也可以为您提供一些其他额外的好处。

您还应该用__attribute__((aligned(64)))标记它们,以防它们被静态分配。

解决这个问题的最简单方法是使对象足够大,这样它们就不能共享缓存线。使用gcc,你可以设置类的对齐(我假设你的对象比缓存线小,因为你会遇到争用):

class foo {} __attribute__((aligned(2 * CL)));

当然,您需要为CL的体系结构插入正确的Cachelinesize(或者将其放入宏中并在那里使用)。我使用的缓存行大小是缓存行大小的两倍,因为据我所知,new并不能保证它确实能确保对齐。因此,由于对象不能保证从缓存行的开头开始,因此您仍然可以在同一个缓存行中获得不同对象的部分(即一个对象的结尾和另一个的开头)。如果始终保持对齐,__attribute__((aligned(CL)))就可以了。当然,这需要你改变你的结构,浪费大量空间。

您也可以在memalign的基础上编写自己的new(请参阅此处了解如何做到这一点)。对于更具创可贴类型的解决方案,您也可以直接使用memalign,并使用placement new将对象放置在分配的空间内。当然,这会让使用这些对象的代码变得不那么好。

您可以使用placement new将对象构造到给定的内存区域中:

  // Instantiate object into a pre-allocated buffer
  obj = new (buf) TheClass();

要获得对齐的缓冲区buf,可以使用memalignsbrkmmap