为什么未对齐的地址访问会导致2次或更多次访问?

时间:2010-10-11 02:21:56

标签: performance cpu cpu-architecture computer-architecture

为什么数据对齐可以更有效地访问并简化CPU设计的正常答案。

相关问题及其答案为here。另一个来源是here。但他们都没有解决我的问题。

假设CPU的访问粒度为4个字节。这意味着CPU一次读取4个字节。我上面列出的材料都说如果我访问未对齐的数据,比如地址0x1,那么CPU必须进行2次访问(一次来自地址0x0,0x1,0x2和0x3,一次来自地址0x4,0x5,0x6和0x7)并结合结果。我不明白为什么。当我发出访问地址0x1时,为什么CPU不能从0x1,0x2,0x3,0x4读取数据。它不会降低性能并导致电路复杂化。

提前谢谢!

4 个答案:

答案 0 :(得分:11)

  

它不会降低性能并导致电路复杂化。

我们认为这是一个错误的假设,因为它确实会进一步加深理解。

Your comment在另一个问题中使用了更合适的措辞(“我不认为它会降低”......)

您是否认为内存架构并行使用多个内存芯片以最大化带宽?并且特定数据项只在一个芯片中,你不能只读取最方便的芯片,并期望它拥有你想要的数据。

现在,CPU和内存可以连接在一起,使得0-7位仅连接到芯片0,8-15连接到芯片1,16-23连接到芯片2,24-31连接到芯片3。所有整数N,存储单元4N存储在芯片0,芯片1中的4N + 1等,并且它们是每个芯片中的第N个字节。

让我们看看存储在每个存储芯片的每个偏移处的存储器地址

memory chip       0       1       2       3
offset

    0             0       1       2       3
    1             4       5       6       7
    2             8       9      10      11
    N            4N    4N+1    4N+2    4N+3



因此,如果从内存字节0-3加载,N = 0,每个芯片报告其内部字节0,这些位都会在正确的位置结束,并且一切都很好。

现在,如果您尝试从内存位置1开始加载一个单词,会发生什么?

首先,我们看一下它的完成方式。第一个存储器字节1-3,存储在偏移0的存储器芯片1-3中,最终位于第8-31位,因为即使您要求它们位于0-23位,这也是这些存储器芯片所连接的位置。这不是什么大问题,因为CPU可以使用与逻辑左移相同的电路在内部调动它们。然后在下一个事务存储器字节4(存储在偏移1的存储器芯片0中)被读入0-7位并且被调到第24-31位,你想要它。

在这里注意一些事情。你要求的字是在偏移量之间分开的,第一个存储器事务从三个芯片的偏移量0读取,第二个存储器事务从另一个芯片的偏移量1读取。这就是问题所在。你必须告诉存储器芯片偏移量,这样它们才能发回正确的数据,偏移量大约为40位,信号速度非常快。现在只有一组偏移信号连接到所有存储器芯片,为了进行未对齐存储器访问的单个事务,您需要运行到每个存储器芯片的独立偏移(称为地址总线BTW)。对于64位处理器,您将从一个地址总线更改为八个,增加近300个引脚。在CPU使用700到1300个引脚的世界中,这几乎不能称为“电路没有太多增加”。更不用说来自许多额外高速信号的噪声和串扰的大幅增加。

好吧,这并不是那么糟糕,因为地址总线上一次最多只能有两个不同的偏移,一个总是另一个加一个。因此,您可以通过一条额外的线路到达每个存储器芯片,实际上说(读取地址总线上列出的偏移量)或(读取下面的偏移量)这是两种状态。但现在每个内存芯片中都有一个额外的加法器,这意味着它必须在实际进行内存访问之前计算偏移量,这会降低内存的最大时钟速率。这意味着如果您希望未对齐访问更快,则对齐访问会变慢。由于99.99%的访问权限可以进行对齐,因此这是净损失。

这就是为什么未对齐访问分为两个步骤的原因。因为地址总线由所涉及的所有字节共享。这实际上是一种简化,因为当你有不同的偏移时,你也有不同的缓存行,所以所有缓存一致性逻辑必须加倍才能处理CPU内核之间的两次通信。

答案 1 :(得分:0)

在我看来,这是一个非常简单的假设。该电路可能涉及多层管道和缓存优化,以确保读取某些内存位。此外,内存读取也被委托给内存子系统,这些内存子系统可以根据性能和设计复杂性不同的顺序构建,以便按照您的想法进行读取。

然而,我确实添加了警告,我不是cpu或内存设计师所以我可以说一个缸。

答案 2 :(得分:0)

问题的答案就在于问题本身。

CPU的访问粒度为4个字节。 因此它只能以4个字节的块来填充数据。

如果您访问过地址0x0,CPU会给出从0x0到0x3的4个字节。

当您发出从地址0x1访问数据的指令时,CPU会将其作为从0x1开始的4字节数据的请求(即0x1 to 0x4)。这不能以任何其他方式解释,主要是因为CPU的粒度。因此,CPU会从0x0 to 0x3& 0x4 to 0x7(ergo,2次访问),然后将0x1 to 0x4的数据放在一起作为最终结果。

答案 3 :(得分:0)

寻址4个字节,第一个字节在左侧错位于0x1而不是0x0意味着它不会在字边界上启动并溢出到下一个相邻字。第一次访问将3个字节抓取到字边界(假设一个32位字),然后第二次访问以完成存储器寻址实现的4字节32位字的模式抓取字节0x4。目标代码或汇编程序有效地透明地对程序员进行第二次访问和连接。最好在可能的情况下保持字边界,通常以4个字节为单位。