我试图确切地了解gcc中的aligned属性如何工作,以及如何将其用于创建高速缓存行对齐的数据结构。我有一个具有2个成员的结构,我想要在不同的缓存行中使用,其中缓存行为64字节。我认为以下内容 不够好,因为它只能保证单个成员的对齐:
struct alignTo64ByteCacheLine_BAD {
int _onCacheLine1
int _onCacheLine2 __attribute__((aligned(64)))
}
但是,以下两种结构都可以保证将其成员放在不同的缓存行中吗?另外,结构本身上的aligned(64)属性会将结构扩展为64字节的倍数以便在数组中使用,还是必须手动完成?
struct alignTo64ByteCacheLine1 {
int _onCacheLine1
int _onCacheLine2 __attribute__((aligned(64)))
} __attribute__((aligned(64)))
struct alignTo64ByteCacheLine2 {
int _onCacheLine1 __attribute__((aligned(64)))
int _onCacheLine2 __attribute__((aligned(64)))
}
答案 0 :(得分:1)
我有一个具有2个成员的结构,我想要在不同的缓存行上 缓存行为64字节。我认为以下不是很好 足够,因为它只能保证单个对齐 成员:
struct alignTo64ByteCacheLine_BAD { int _onCacheLine1 int _onCacheLine2 __attribute__((aligned(64))) }
您错了:上面的代码将导致两个成员都在64位地址上对齐。这是基于以下事实:
结构的对齐要求必须是每个成员的对齐要求的倍数(否则不能保证至少一个成员的对齐),并且
第一个成员之前不能有填充。
因此,对于只有两个成员的结构,为第二个指定对齐方式可确保第一个至少具有严格的对齐方式。因此,此替代方案与您其他两个方案具有相同的实际效果。
此外,这可以确保每个成员都在其缓存行的开始处,这比您表达的要强。如果您确实只需要将成员放在不同的缓存行上,则仅对齐第二个就足够了,因为必须将第一个成员放在内存中的第二个成员之前。
但是,请注意,这似乎效率极低。对齐要求将要求编译器将此结构填充到(至少)128个字节的整体大小,其中仅使用8个字节(由于我们在谈论GCC,我们知道我们有4个字节的int
s)。每个成员将是其缓存行中的唯一对象。您没有说为什么要这么做,但是它似乎很可能会影响您的缓存命中率。
此外,结构本身上的aligned(64)属性是否会填充 将其构造为64字节的倍数以用于数组,或者这样做 必须手动完成?
结构大小将被填充为其对齐要求的倍数,以确保类型数组不会强制任何元素未对齐。
答案 1 :(得分:0)
由于该问题被标记为C ++,我会这么说
alignas
:https://en.cppreference.com/w/cpp/language/alignas
alignas说明符可以应用于变量的声明 或非位域类数据成员,也可以将其应用于 类/结构/联合或枚举的声明或定义。
以下是上面链接中的一些示例:
// every object of type sse_t will be aligned to 16-byte boundary
struct alignas(16) sse_t
{
float sse_data[4];
};
// the array "cacheline" will be aligned to 128-byte boundary
alignas(128) char cacheline[128];
std::hardware_destructive_interference_size
定义为两个对象之间的最小偏移,以避免错误共享(因此,缓存行的大小)。因此alignas(std::hardware_destructive_interference_size)
将以可移植的方式工作。