C ++中的虚假共享

时间:2012-02-19 19:13:01

标签: c++ multithreading

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

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

3 个答案:

答案 0 :(得分:3)

您可以分别对glibc或Windows CRT系统使用memalign_aligned_alloc。你甚至可以使用像nedmalloc这样的自定义分配器并让它对齐块,这也可以为你提供一些额外的奖励。

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

答案 1 :(得分:3)

解决此问题的最简单方法是使对象足够大,以至于无法共享缓存行。使用gcc你可以设置类的对齐方式(我假设你的对象小于高速缓存行,因为你遇到了争用):

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

当然,您需要为CL的架构插入正确的Cachelinesize(或者将其放入宏中并在那里使用)。我使用了两倍大小的缓存行,因为我记得new并不能保证它实际上会确保对齐被保留。由于无法保证对象在高速缓存行的开头处开始,因此您仍然可以在同一个高速缓存行中获取不同对象的一部分(即一个对象的结尾和另一个对象的开头)。如果始终保留对象,__attribute__((aligned(CL)))就可以了。当然,这需要你改变你的结构并浪费很多空间。

您还可以根据new编写自己的memalign(查看here了解如何执行此操作)。对于更多的bandaid解决方案,您还可以直接使用memalign并使用placement new将对象放入分配的空间内。当然,这会使使用这些对象的代码变得不那么好。

答案 2 :(得分:1)

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

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

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