题
诚然我不明白这一点。假设你有1个字节的长度的记忆单词记忆。为什么不能访问4字节长的变量上未对齐地址(即不能被4整除)单个存储器访问,因为它与对齐的地址的情况下?
解决方案
这是许多潜在的处理器的限制。它通常可以通过做4低效的单字节工作围绕获取,而不是一个有效的字获取,但许多语言说明符决定它会更容易只是为了取缔他们,并强制所有内容保持一致。
有在此链接该OP发现的。
其他提示
上的现代处理器的存储器子系统被限制为在粒度和其字大小的对准存取存储器;这是有很多原因的情况。
速度
现代处理器具有数据必须被拉动通过高速缓冲存储器的多个等级;支撑单字节读将使存储器子系统吞吐量紧密结合到执行单元的吞吐量(又名CPU限制的);这是所有让人想起 PIO模式是如何通过DMA 超越对于许多的硬盘驱动器中相同的原因。
在CPU的总是强>读取在其字的大小(在32位处理器4个字节),所以当你不对齐地址的访问 - 在处理器上支持它 - 所述处理器将要读取多个单词。 CPU将读取的内存,您的请求的地址跨越每一个字。这使得访问所请求的数据所需的存储器记录,高达2X数量的扩增。
正因为如此,它可以非常容易地比较慢读取两个字节超过四个。例如,假设你在内存中的结构,看起来像这样:
struct mystruct {
char c; // one byte
int i; // four bytes
short s; // two bytes
}
在一个32位处理器,将最有可能被像对准如下所示:
该处理器可以在一个事务读取的这些部件的每
假设您有该结构的填充版本,也许从那里被包装为传输效率的网络;它可能看起来是这样的:
读取的第一个字节将是相同的。
当你问处理器给你从0×0005 16位它将不得不从0x0004读一个字和左移1个字节以将其放置在一个16位寄存器;一些额外的工作,但大多数可以处理在一个周期。
当你问从0×0001,你会得到一个2X放大32位。处理器将从0x0000读入结果寄存器和从0x0004再次左移1字节,则读入临时寄存器,右移3个字节,然后与结果寄存器OR
它。
范围
对于任何给定的地址空间,如果该体系结构可以假定2个LSB总是0(例如,32位的机器),那么它可以访问4倍以上的存储器(2个保存的比特可以表示4种不同的状态),或相同容量的内存与像标志2位。服用2个LSB关的地址会给你一个4字节对齐的;也被称为4个字节的步幅。一个地址递增,它被有效地递增位2,位不为0,即,每个时间,最后的2位将总是继续00
。
这甚至可以影响系统的物理设计。如果地址总线需要2个更少的比特,可以存在于该电路板上的CPU 2个较少的引脚,和2点更少的痕迹。
原子性
在CPU可以在原子的存储器中的对齐的字进行操作,这意味着没有其他指示可以中断操作。这是很多关键锁定释放的数据结构和其他并发范例
结论
一个处理器的存储器系统是相当多的更复杂,比这里描述的参与;在的x86处理器实际上是如何解决内存可以帮助(多处理器工作同样)。
有米任何更多的实惠秉承内存对齐,你可以rel="noreferrer">这个IBM文章在
一个计算机的主要用途是转换数据。现代存储器架构和技术已经优化了几十年,以促进获得更多的数据,IN,OUT和之间更多,更快的执行单元,在一个高度可靠的方式。 另一个对准换性能,我前面提到的是对高速缓存行其是(例如,在某些CPU)64B对准。 有关多少性能可以通过利用高速缓存来获得更多的信息,看看的的处理器高速缓存的影响廊;从这个问题尺寸 的高速缓存行的理解可以是用于特定类型的程序优化的重要。例如,数据的对准可确定操作是否触摸的一个或两个高速缓存行。正如我们在上面的例子中所看到的,这可以很容易地意味着在未对准情况下,操作将是两次慢。加成:缓存
您可以与一些处理器(的Nehalem处理器能做到此),但先前的所有存储器访问被在64位对齐(或32位)线,这是因为总线是64个位宽,则有以一次取64位,这是更容易显著在对齐的64个比特“块”抓取这些。
所以,如果你想获得的一个字节,你获取的64位数据块,然后屏蔽掉你不想位。方便快捷,如果你的字节是在右端,但如果是在64位块的中间,你不得不屏蔽掉不需要的位,然后到正确的位置数据移位。更糟的是,如果希望一个2字节的变量,但是这是在2个组块分割,然后,需要两倍的所需的存储器访问。
所以,每个人都认为内存很便宜,他们刚才的编译器将处理器的数据块的数据大小,以便您的代码运行速度更快,更有效地在浪费内存的成本。
从根本上说,其原因是因为在存储器总线有一些特殊的长度,其是多,比存储器大小要小得多。
因此,CPU读出芯片上的L1高速缓存,其通常32KB这些天的。但是,L1高速缓存连接到CPU存储器总线将具有高速缓存线大小的极大小的宽度。这将是128 位
的量级所以:
262,144 bits - size of memory
128 bits - size of bus
未对齐存取有时会重叠两个高速缓存行,而这将需要以获得该数据读一个全新的缓存。它甚至可能会错过所有的出路到DRAM。
此外,CPU的一些部分将具有放置在它的头放在一起的单个对象出这两种不同的高速缓存行,每个有一块数据。在一行上,这将是在非常高的序位,在另一方面,非常低序位。
有将完全集成到手柄对齐的对象移动到所述CPU数据总线的所需位管线的专用硬件,但是这样的硬件可以是缺少未对准的目的,因为它可能使使用超速那些晶体管更有意义正确优化的程序。
在任何情况下,第二存储器读取有时需要将管道专用于修补错位存储器操作慢下来没有多大关系的专用硬件如何为(假设和愚蠢)。
@joshperry赋予优异的这个问题的答案。除了他的回答,我有一些数字,显示图形,其被描述,尤其是2倍的放大效果。这里有一个谷歌电子表格中的链接显示的效果怎样不同的词对齐样子。 除了这里的一个 Github的要点链接与测试的代码。 测试码从的文章由Jonathan Rentzsch其中@joshperry写入引用。这些测试是在MacBook Pro上用四核2.8 GHz的英特尔酷睿i7 64位处理器的16GB RAM,并运行。
如果用字节可寻址存储器的系统中有一个32位宽的存储器总线,这意味着有效地有其全部连接到读取或写入同一地址4字节宽的存储器系统。对准的32位读操作将需要存储在同一地址中的所有四个存储系统的信息,因此,所有系统可同时提供数据。未对齐的32位读需要一些存储系统,以从一个地址返回数据,以及一些从下一个更高的地址返回数据。虽然有经过优化,能够满足这样的要求有些记忆系统(除了他们的地址,他们有效地有一个“加一”信号,使它们使用一个地址一个高于规定)这样的功能,增加了相当大的成本和复杂性的存储器系统;大多数商品存储器系统根本无法在同一时间返回不同的32位字的部分。
如果你有一个32位数据总线,连接到所述存储器的地址总线的地址线将从A <子> 2 子>启动,因此,只有32位对齐的地址可以在一个单一的总线周期来访问。
因此,如果一个字跨越一个地址对准边界 - 即A <子> 0 子>为16/32位数据或A <子> 1 子>针对32位的数据是不是零,两个总线周期需要获得的数据。
一些架构/指令集不支持对齐访问,并且将生成的这些尝试的异常,所以编译器生成的未对齐存取码不仅需要附加的总线周期,但额外的指令,使得它甚至不太有效。
在的PowerPC可以从没有问题奇数地址加载的整数。
Sparc和I86和(我认为)Itatnium提高硬件异常时,你试试这个。
一个32位的负载VS 4级8位的负载心不是要作出很大的差异在大多数现代处理器。数据是否已在缓存中是否会产生更大的影响。