Alignment 为什么会有比一个词更大的对齐?
好的,我知道存储与CPU字大小块对齐的数据可以提高访问速度。但这些块通常是16、32或64位,为什么还有其他的对齐值,比如128bit或256bit?我的意思是,在PC机中没有任何处理器使用如此大的寄存器。我猜这和CPU缓存有关?我也在辅助存储中看到过这种排列(但实际上它们更大——例如10240位)。许多处理器都有128位SIMD寄存器(例如x86 SSE寄存器、ARM Neon寄存器、MIPS SIMD体系结构寄存器);x86 AVX将SSE寄存器扩展到256位,AVX-512将大小再次翻倍 然而,需要更大的路线还有其他原因。正如您所猜测的,缓存行为是使用较大对齐的动机之一。将较大的数据结构与缓存线的大小对齐(x86通常为64字节,现代系统中通常不小于32字节)可以保证对任何成员的访问都会将相同的其他成员带入缓存。这可以通过将经常使用(也称为热)或通常同时使用的成员放在同一个缓存块中来减少缓存容量使用和未命中率Alignment 为什么会有比一个词更大的对齐?,alignment,cpu,Alignment,Cpu,好的,我知道存储与CPU字大小块对齐的数据可以提高访问速度。但这些块通常是16、32或64位,为什么还有其他的对齐值,比如128bit或256bit?我的意思是,在PC机中没有任何处理器使用如此大的寄存器。我猜这和CPU缓存有关?我也在辅助存储中看到过这种排列(但实际上它们更大——例如10240位)。许多处理器都有128位SIMD寄存器(例如x86 SSE寄存器、ARM Neon寄存器、MIPS SIMD体系结构寄存器);x86 AVX将SSE寄存器扩展到256位,AVX-512将大小再次翻倍
例如,考虑具有32字节高速缓存块的缓存访问的以下结构:
struct {
int64_t hot1; // frequently used member
int64_t hot2; // frequently used member
int64_t hot3; // frequently used member
int64_t hot4; // frequently used member
// end of 32-byte cache block if 32-byte aligned
int64_t a; // always used by func1, func2
int64_t b; // always used by func2
int64_t c; // always used by func1, func3
int64_t d; // always used by func2, func3
// end of 32-byte cache block if 32-byte aligned
int64_t e; // used by func4
int64_t f; // used by func5
int64_t g; // used by func6
int64_t h; // used by func7
}
如果结构是32字节对齐的:
- 对任何热成员的访问将使所有热成员进入缓存
- 调用
、func1
或func2
将func3
、a
、b
和c
带入缓存;如果这些函数在时间上在附近调用,那么数据仍将在缓存中d
- 对
或hot1
的访问会将位于hot2
之前的16字节无关数据带入缓存,而不会自动将hot1
和hot3
加载到缓存中hot4
- 访问
或hot3
会将hot4
和a
带入缓存(可能是不必要的)b
- 调用
或func1
更有可能遇到func2
和a
的缓存命中,因为它们与b
和hot3
位于同一个缓存块中,但未命中hot4
和c
,并且将d
和e
带到缓存f
- 调用
会降低func3
和e
进入缓存的效率,但不会f
和a
b
和
可以生成缓冲区的起始地址或缓冲区中的字节数,因此缓冲区中的大对齐也很方便
还可以利用对齐来提供指针压缩(例如,64字节对齐将允许32位指针指向256 GiB而不是4 GiB的地址,但在加载指针时会导致6位左移)。类似地,指向对齐对象的指针的最低有效位可用于存储元数据,在使用指针之前,需要使用和将位归零。许多处理器都有128位SIMD寄存器(例如x86 SSE寄存器、ARM Neon寄存器、MIPS SIMD体系结构寄存器);x86 AVX将SSE寄存器扩展到256位,AVX-512将大小再次翻倍
然而,需要更大的路线还有其他原因。正如您所猜测的,缓存行为是使用较大对齐的动机之一。将较大的数据结构与缓存线的大小对齐(通常为6
SSE: 16 bytes
AVX: 32 bytes
cache-line: 64 bytes
page: 4096 bytes
SSE: _mm_load_ps() and _mm_store_ps()
AVX: _mm256_load_ps() and _mm256_store_ps()
SSE: _mm_loadu_ps() and _mm_storeu_ps()
AVX: _mm256_loadu_ps() and _mm256_storeu_ps()