确保与std :: hardware_constructive_interference_size共享的正确方法

时间:2019-02-03 01:29:58

标签: c++ alignment c++17

什么是正确且可移植的方法,以确保在足够小以适合缓存线的结构中真正共享?仅确保结构足够小就足够了吗?还是也必须在缓存边界上对齐?

例如,假设高速缓存行的大小为64个字节,那么以下内容是否足够?

struct A {
  std::uint32_t one;
  std::uint32_t two;
};

还是我必须这样做?

struct alignas(std::hardware_constructive_interference_size) A {
  std::uint32_t one;
  std::uint32_t two;
};

注意:这将始终在堆栈上,因此不需要过度对齐的内存分配。


另一项跟进,是否足以确保不存在虚假共享?

struct A {
public:
  alignas(hardware_destructive_interference_size) std::uint32_t one;
  alignas(hardware_constructive_interference_size) std::uint32_t two;
};

还是必须这样做(例如说hardware_constructive_interference_size <hardware_destructive_interference_size?)

struct A {
public:
  alignas(hardware_destructive_interference_size) std::uint32_t one;
  alignas(hardware_destructive_interference_size) std::uint32_t two;
};

1 个答案:

答案 0 :(得分:4)

在第二变型目前是可以做是最好的。

然而,有对齐到高速缓存行的大小没有100%可移植的方法。常量hardware_constructive_interference_sizehardware_destructive_interference_size只是提示。他们是编译器的最佳猜测。最终,您在编译时不知道L1高速缓存行的大小。

但是,在实践中,这通常并不重要,因为对于大多数的体系结构有一个典型的高速缓冲存储器线的大小,如64个字节用于x86

甚至更多,在你的例子小结构一样,它始终是足够的自然对齐结构,以确保它完全是一个高速缓存行内。在您的具体示例中,这意味着

struct alignas(8) A {
  std::uint32_t one;
  std::uint32_t two;
};

将始终确保真正的共享,而不管在运行时实际L1高速缓存行大小的,条件是该高速缓存行大小为8个字节或更大。 (如果它较小,您将不会真正拥有真正的共享。)

关于后续问题:第二个变体将确保没有错误共享。第一种变体可能会导致错误共享,因为高速缓存行大小实际上可能是hardware_destructive_interference_size,在这种情况下,您将具有错误共享(假设hardware_constructive_interference_size <hardware_destructive_interference_size)。

但是实际上,hardware_destructive_interference_sizehardware_constructive_interference_size对于大多数体系结构将具有相同的价值。鉴于这两个常量都不能为您提供真正的L1缓存行大小,而只是提供了编译时的猜测,因此这有点工程化。