memory - 为什么 CPU 访问对齐的内存
问题描述
互联网的好人!
在过去的几天里,我一直在阅读有关 CPU 如何访问内存以及如果访问的对象分布在 CPU 访问的不同块上,它会如何变慢。
用一个非常笼统和抽象的话来说,如果我有一个从 0x0 到 0xF 的地址空间,其中一个字节的单元格,并且 CPU 以 4 字节的块读取内存(即,具有四字节的内存访问粒度),然后,如果我需要读取位于单元格 0x0 - 0x3 中的 4 字节大小的对象,CPU 将在一次操作中完成,而如果同一对象占用单元格 0x1 - 0x4,则 CPU 需要执行两次读取操作(读取内存首先在 0x0 - 0x3 中,然后在 0x4 - 0x7 中),移位字节并组合两个部分(或中断,如果它不能进行非对齐访问)。这再次发生,因为 CPU 可以读取 4 字节块的内存(在我们的抽象情况下)。我们还假设,CPU 在一个高速缓存行内进行这些读取,并且在读取之间不需要更改高速缓存的内容。
因此,在这种情况下,CPU 可以读取的每个块的开头都驻留在地址为 4 的倍数的内存单元中(对吗?)。好的,我对 CPU 读取块的原因没有任何疑问,但是why exactly the beginning of each chunk is aligned in such a way?
如果参考上一段中的示例,why exactly CPU cannot read a chunk of 4 bytes starting from 0x1?
据我所知,CPU 非常清楚 0x1 的存在。那么所有的fuzz都是因为内存控制器无法访问从0x1开始的内存块吗?还是因为在某些架构上保留了处理器字中的几个 LSB?或者它们被保留的事实是对齐访问的结果,而不是它的原因(似乎已经是第二个问题,但我会留下它,因为在我写这个问题时我觉得它们是相关的)?
这里有很多关于这个主题的答案(比如这个和这个)和在线文章(比如这个和这个),但是在所有的资源中都有关于现象本身及其后果的很好的解释,但没有解释为什么 CPU无法读取从“介于”字节边界之间的内存块(或者我可能看不到它)。
解决方案
考虑一个简单的 CPU。它有 32 个 RAM 芯片。每个芯片提供一位内存。CPU 产生一个地址,将其传递给 32 个 RAM 芯片,然后 32 位返回。第一个 RAM 芯片保存字节 0、4、8、12、16 等的第 0 位。第二个 RAM 芯片保存字节 0、4、8、12、16 等的第 1 位。第九个 RAM 芯片保存字节 1 的第 0 位, 5, 9, 13, 17 等
所以你看到它们之间的 32 个 RAM 芯片可以产生字节 0 到 3 的位 0 到 7,或字节 4 到 7,或字节 8 到 11 等。它们无法产生字节 1 到 4。
推荐阅读
- javascript - 如何防止冻结nodejs expresjs上的获取路由
- python - 如果布尔值不等于另一个布尔值,则反转布尔值的最短方法
- javascript - 在 django 中获取整个 linkvertise 引用地址
- raspberry-pi - Micropython 从 FLARM 设备 (NMEA) 接收 uart 数据
- javascript - 使用 Splunk JS SDK 创建搜索请求时出错
- javascript - 为什么我的图像拉伸到最大尺寸?
- python - Gitlab CI/CD 在“清理项目目录和基于文件的变量”时失败,并显示“错误:作业失败:退出代码 1”
- architecture - Salesforce 可以在本地 Kubernetes 集群中运行吗?
- python - 使用 Python 的 multiprocessing.shared_memory 我仍然需要创建我正在共享的对象的(初始)副本。还是我?
- php - 有没有办法防止 Guzzle 在 POST 请求中将 [] 附加到具有多个值的字段名称?