内存对齐和访问粒度在程序集中如何工作?

如何解决内存对齐和访问粒度在程序集中如何工作?

我试图了解 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 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res