如何解决内存对齐和访问粒度在程序集中如何工作?
我试图了解 CPU 内存对齐和 CPU 内存访问粒度是如何工作的,但我有点困惑,因为我找不到 CPU 的访问粒度是什么以及两者如何相互作用以影响性能。所以让这个汇编代码运行 x86-64 处理器:
start0:
.byte 0 # at address 0x0
start1:
.byte 1 # at address 0x1
start2: # at address 0x2
.quad 2
start3: # at address 0x10 for example
.quad
movb start0,%al # (1) aligned
movb start1,%al # (2) unaligned
movq start2,%rax # (3) unaligned
movq start3,%rax # (4) aligned
这是否意味着
(1)
会导致 CPU 仅从内存中读取 1 个字节,否则 CPU 将读取 64 位内存并移动不需要的部分。
(2)
会导致 CPU 在地址 0x0 处读取,但它会读取多少是 64 位或其他内容?。
(3)
这是否会导致 CPU 执行两次内存读取,一次在地址 0x00,另一次在地址 0x8
,然后再次操作它们以获得正确的值?。
(4)
会正常从地址 0x10 读取 8 个字节,对吗?
还有我怎么知道运行 CPUID
的 CPU 的访问粒度似乎没有结果。我已经知道我的 CPU 的对齐方式是 8 字节对齐。
解决方法
不,您可以在可执行文件中使用该代码自行尝试并使用调试器。如果 .p2align 3
之前没有 start3
,它会错位。 2 + 8 = 0xa,而不是 0x10。汇编器只是根据您的指令将字节发送到输出中,.quad
并不意味着对齐。
至于问题的主要部分:不,1 字节加载逻辑上仅访问该 1 字节。例如如果您从 MMIO 地址加载,则设备只会看到 1 字节访问,而不是 qword 访问。
我已经知道我的 CPU 的对齐方式是 8 字节对齐。
除了 8 字节加载的性能优势之外,没有任何意义。 x86-64 可以执行 1、2、4、8 或 16 字节的加载。 (对于 AVX 或 AVX-512,也可以加载 32 或 64 字节。)但它允许任何这些大小的未对齐加载。某些形式的 16 字节加载(如 SSE 内存操作数)需要 16 字节对齐,但低于 16 的则不需要。 (您可以在 EFLAGS 中设置一个对齐检查 (AC) 标志,但它在大多数情况下不是很可用,因为 memcpy 的编译器和 libc 实现自由地使用未对齐访问。)即使在微体系结构上,现代 x86 硬件也确实对非对齐访问进行了高效的访问。它的缓存。
对于可缓存 RAM,除了性能之外,CPU 在内部所做的事情是不可见的,但在逻辑上是等效的。
在现代 x86 CPU 中,它实际上是从 RAM 加载的整个 64 字节缓存线。但是我们可以或多或少地证明,即使是硬件也在对缓存进行单字节访问,因为字节存储不会导致相邻负载的存储转发停顿,以及其他因素。见Can modern x86 hardware not store a single byte to memory?
请注意,对于单字节存储甚至加载,某些非 x86 CPU 的缓存访问速度确实较慢。 (Are there any modern CPUs where a cached byte store is actually slower than a word store?)。 x86 CPU 专为高效的未对齐和单字节访问而设计,因此软件可以继续使用它们。但在历来不支持未对齐访问的 ISA(如 MIPS 或某种程度上的 ARM)上,软件通常会避免未对齐访问,因此硬件花费大量晶体管以使其更快的好处较少。
(此外,当前的 x86 设计针对这样一个用例,即需要花费更多的晶体管和功率来获得较小的速度提升,而大多数 ARM 设计却没有。此外,x86 CPU 试图加快现有二进制文件的速度的因素做,不太希望让人们重新编译或重新设计软件以避免诸如未对齐访问之类的事情. 综上所述,我认为现代 ARM / AArch64 具有合理的未对齐 / 字节访问,但不是现代 x86 对任何负载所做的零惩罚不跨越缓存行边界。)
脚注 1:注意这适用于 asm;如果您使用 C 编写,则语言/ABI 规则适用,直到编译器实际确定 asm。请参阅 Why does unaligned access to mmap'ed memory sometimes segfault on AMD64? 以获取示例,其中未对齐的 C 指针违反编译器的假设,导致在针对 x86-64 进行编译时出现问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。