g++ 如何对齐内存以确保对齐从缓存行的开头开始?
How does g++ align memory to make sure the alignment starts at the beginning of a cacheline?
我在 g++ 中读到我们可以做到:
struct foo {
int a, b, c;
} __attribute__((__aligned__(64)));
因此结构 foo 的大小为 64 ---通常是缓存行的大小。 当我们需要访问此缓存行时,CPU 可以一次性加载 Foo。
这是否意味着 CPU 可以在任何内存地址---不一定是整数 64 的内存地址从 L2 加载 foo?
想象 foo 在内存中的地址类似于 0xFFFF3,CPU 是否需要读取两个缓存行来加载 foo?
谁能为我澄清这一点?
PS:我在 CentOS 6.2 上使用 g++ 64 位
对齐与内存中结构地址的起始位置有关。如果结构的大小小于或等于 64 字节,那么您是对的,您的结构将适合一行缓存,但如果结构大于 64 字节,则始终为 false。
对齐仅与该类型的局部或全局变量的起始位置相关。当您编写试图爆发处理器功率的算法时,请优化与 64 字节对齐的数据访问,以便您可以处理 64 个连续字节而不会出现任何缓存错误。顺便说一下,当数据对齐到 64 个字节时,编译器的优化器会创建更优化的代码。
一个快速测试是创建一个小程序,并生成对齐和未对齐的汇编程序代码,并比较您获得的汇编程序。(例如访问局部向量的小循环),启用优化器(-O2 或 -O3)。
PS:使用堆时,您可以自己分配
struct foo *myFoo = (malloc(size(struct foo)+15) + 15) & (~ 0x0f);
似乎有两个问题被掩盖为一个问题。我会尽力回答他们。
首先,对齐问题。一般来说,C++编译器对缓存行等一无所知(或假装一无所知)。相反,它只是确保此类型的所有对象都与 64 字节边界对齐(前提是它们本身更小或大小等于 64)。这是编译器作业完成的地方。
现在,我们需要关注 CPU 行为。由于缓存行大小为 64 字节,当对象在 64 字节边界上对齐时,我们确定加载整个对象时将位于缓存中。因此,对对象成员的访问保证由 L1 缓存提供,而不是更昂贵的方式(例如 L2)。
由于 L2是一个大得多的缓存,因此没有理由尝试对齐代码以遵守 L2 边界。
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 如何创建一个QTableWidgetItem,用长文本右对齐,左边有省略号
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- 64位机器上的C++内存对齐
- 为什么我可以将变量存储在不是其最小对齐方式的倍数的地址?
- 使 std::vector 分配对齐内存的现代方法
- C++ cout 将双精度对齐到精度 2 并正确对齐
- 在 64 位边界上对齐C++结构数组?
- 使用 g++7 构建的代码在访问未对齐的内存时崩溃
- 在 capnp FlatArrayMessageReader 的对齐内存缓冲区中接收 zmq 消息
- 是否值得对齐变量?
- 初始化派生结构的基部分/意外打包派生结构字段以对齐基结构的间隙
- gcc 中的多个对齐属性是否可以用于保证缓存行分隔?
- g++ 如何对齐内存以确保对齐从缓存行的开头开始?
- 对齐非 POD 结构的缓存
- 在使用GCC时,如何使用__Align__中的大小进行缓存对齐
- 由于 FPU 或缓存而与 8 字节边界对齐的双精度
- 缓存行、错误共享和对齐
- 如何以及何时对齐缓存行大小
- 如何确定地址是否与缓存对齐