为什么大多数常见处理器的位数都是2的幂?

Sam*_*mFF 34 cpu computer-architecture cpu-architecture

目前广泛使用的大多数处理器/CPU 的位数都是 2 的幂(通常为 32 和 64,但也有 16、8 和 4 位)。

尽管位数的含义并不一致(有人说是字长、寄存器大小、指令宽度、数据或地址总线宽度等),但所有这些几乎总是 2 的幂。

我知道有一些例外,例如 Intel 8086 有一个 20 位地址总线,但正如我所说,它通常是2 的幂。

为什么会发生这种情况,有哪些例外情况,为什么?

Joh*_*man 28

8位字节

其中大部分源于 8 位字节的采用。随着 1964 年 IBM 360 系列计算机的推出,这种方式变得流行起来。当年的 IBM 技术期刊一期中,对这一选择做出了解释:

字符大小,6 vs 4/8:在字符大小中,根本问题是十进制数字需要 4 位,字母数字字符需要 6 位。考虑了三种明显的替代方案 - 全部 6 位,数字数据浪费 2 位;4 位用于数字,8 位用于字母数字,2 位浪费在字母数字上;4 位数字,6 位字母数字,这需要采用 12 位模块作为最小可寻址元素。还对包含十进制数字对的二进制重新编码的 7 位字符进行了简要检查。

4/6 方法被拒绝,因为 (a) [it] 希望它具有操作字符流和寻址单个字符的多功能性和能力,即使在不使用十进制算术的模型中也是如此,(b) 将字母字符限制为6 位似乎是短视的,并且 (c) 这种方法的工程复杂性很可能比角色中浪费的位花费更多。

在 IBM 702-7080 和 1401-7010 系列以及其他制造商的系统中使用的直 6 方法具有使用熟悉、现有 I/O 设备、简单的规范字段结构以及与一个 48 位浮点字和一个 24 位指令字段。

IBM 650-7074 系列和其他地方使用的 4/8 方法具有更高的编码效率、字母集中的备用位(允许该集增长)以及与 32/64 位浮点字和16位指令字段。这些因素中最重要的是编码效率,这是因为业务记录中数字数据的使用频率是字母数字数据的两倍多。这种效率意味着,对于给定的硬件投资,可以更好地利用核心存储、更快的磁带和更大容量的磁盘。

总体而言,按照当时的标准,8 位字节允许相当大的字符集,并且每个字节还允许两个 BCD 数字。

转向字节寻址

最早的计算机设计的首要任务是尽可能快地处理数字。数字通常存储在机器字中,所需的数字范围决定了字的大小。指令通常是单个字,并且每条指令通常有一个地址。指令中地址字段的大小决定了存储器的大小。IBM 704/709就是一个例子;它最多有 4096 个 36 位字,每个字有 6 个字符,每个字符 6 位。地址是 12 位。

随着计算机使用范围的扩大,处理文本数据变得越来越重要。在字寻址机器中执行此操作充其量是很麻烦的。字节寻址机器允许您轻松访问单个字符,但需要更大的地址字段。同时,磁芯存储器允许构建比真空管、静电存储或延迟线大得多的存储器

这些发展实质上迫使计算机拥有更大的地址空间,并结束了每条指令都有一个地址的做法。

较大的数据项

每个数据项拥有整数字节显然会让事情变得更简单。这个级别的简单性是非常值得的,因为在电子部件(早期的电子管,此后的晶体管)预算有限的情况下使计算机尽可能快地运行一直很重要。因此两个字节(16 位)就成为一个明显的大小。

对于较大尺寸,电子设计中会出现两个因素:

数东西

实现指令通常需要对数据项的字节(或位)进行计数。使用二的幂可以使这些计数器的电子设备更简单。要计数 4 个字节,需要一个 2 位计数器,它可以保存 0 到 3 的值。计数 3 个字节仍然需要一个 2 位计数器,但其中一个值没有意义,必须被视为特殊的计数器。硬件中的情况。

通过串行线路发送数据需要对每个项目的位进行计数,这是 8 位字节的另一个好处。3 位计数器将处理它们,无需任何特殊情况。

IBM 360 选择了 32 位地址(尽管它在第一个十年只允许使用 24 位内存地址),一旦建立起来,使用 8 位字节和 32 位地址与 IBM 竞争比使用 8 位字节和 32 位地址要容易得多。你想做一些不同的事情。

内存获取和数据对齐

如果数据项“对齐”,则从内存中获取数据会更简单。这意味着它们的地址是其大小的倍数。因此,对于像 IBM 360 这样的字节寻址机器,单个字节可以位于任何地址。如果两字节(16 位)项位于偶数地址,则该项是“对齐的”。如果四字节(32 位)项的地址是 4 的倍数,则该项是对齐的。

20 世纪 60 年代到 1990 年代的许多计算机设计都拥有可以在一次操作中从 4 的倍数地址开始读取 4 个字节的内存。如果您的数据项是对齐的,那么您保证能够读取任意两个 -或从内存中一次读取的四字节项目。如果它们没有对齐,有时您需要两次提取。这需要内存访问系统更加复杂,以识别操作未对齐并生成额外的读取。这种复杂性和额外的获取会减慢速度。

大于 4 个字节的项目将需要两次提取,但如果较大的项目是 8 个字节,并且在 8 字节边界上对齐,那么情况会更简单。那么你总是需要两次提取。如果您有未对齐的 8 字节项目,则需要进行三次提取。

在现代快速系统中,读取始终是完整的缓存行,通常为 32 或 64 字节。这些始终是对齐的,并且适合其中的对齐数据项总是完整到达。

相当多的计算机设计将未对齐的读取视为程序错误,并杀死执行该错误的程序。基于 x86 的系统不会这样做,但必须付出复杂性的代价。它们在对齐数据的情况下运行得更快,因此通常会使用它,尽管这不是强制性的。

24位系统

我使用的是 24 位系统,ICL 1900 主机。它使用 6 位字节,每个 24 位字四个字节。这些 6 位字节将其限制为大写文本,而 24 位指针将其限制为 16MB RAM,按照今天的标准来看,这很小。

具有 8 位字节的更现代的 24 位系统仍然限于 16MB 的易于寻址的内存,并且将付出具有不需要的状态的计数器的成本,以及未对齐或浪费一个字节内存的内存项的成本。每个 24 位整数。32 位系统的能力更强,并且以当今的技术可以非常便宜地构建。

历史的教训

有一些有影响力的计算机系统具有 32 位整数和指针,但使用 24 位寻址。它们是 Motorola 68000 和 IBM 360。在这两种情况下,仅使用地址的最低 24 位,但存储在内存中的地址占用了 32 位。

由于这些系统仅限于 16MB RAM,程序员将其他数据存储在空闲的 8 位中。当 16MB RAM 显然不够用并且设计扩展到 32 位寻址时,如果将备用位中存储的数据视为地址的一部分,则存储在备用位中的数据将成为一个严重的问题。

在 68000 系列上,必须更改现有程序以停止使用那些不再备用的位。这在 20 世纪 80 年代后期的 Macintosh 软件更新为 68020 兼容性时在更广泛的计算机行业中最为引人注目,但同样的情况也发生在 Amiga 上,可能还有其他基于 68000 的系统上。

在 IBM 360 的后续产品上,仍然可以运行 24 位地址程序,以及使用更大地址的程序。但潜在的 32 个地址位中只能使用 31 个;牺牲了一个地址位,让硬件能够区分两种代码之间的差异。

后 32 位设计

每个设计过大于 32 位寻址的通用架构的人都知道 360 和 68000,以及 24 位寻址造成了多少痛苦。没有人认真尝试设计像实模式 x86 这样的分段架构来超越 32 位寻址。每个人都使用平面地址空间。地址大小只有几个模糊合理的选择。

  • 40 位寻址很复杂。电子设备在通过位和字节进行计数时具有未使用的值。如果内存读取是 32 位,则 40 位指针始终需要两次读取;如果内存读取是 40 位,则某些 16 位和 32 位读取需要两次读取操作,而某些 64 位读取则需要三次。您可以通过将 32 位数量扩大到 40 位,将 64 位数量扩大到 80 位来减少这一点,但这不是一个好主意 - 见下文。

  • 40 位寻址也不会持续很长时间。它只允许寻址 1024GB,到 2023 年,这对某些市场来说已经是一个问题。将 40 位寻址扩展到更大的地址空间会导致另一轮中断,因为软件会更新以利用它,并且可能会破坏对 40 位的向后兼容性。如果您选择 40 位和 80 位选项,它还会给您带来另一轮对齐复杂性。

  • 48 位或 56 位寻址与 40 位寻址一样复杂,虽然它们可能会持续更长时间,但当您已经走到这一步时,您可能会一直走下去。

  • 64 位比 40、48 或 56 位更容易构建。它会持续更长时间。其寄存器大小与标准浮点数据大小匹配。这似乎合乎逻辑。

第一个通用后 32 位微处理器是 1991 年发布的 MIPS R4000、1991 年发布的 Kendal Square Research KSR-1 以及 1992 年发布的 DEC Alpha。

  1. 我不知道 MIPS 项目的很多细节,但它是他们的 32 位 R2000 和 R3000 微处理器的 64 位扩展。SGI 在 1991-92 年陷入财务困难时收购了 MIPS,以确保其工作站产品的处理器供应。

  2. KSR-1 是一台超级计算机,至少有 8 个他们自己设计的 64 位微处理器。但它并不成功。

  3. DEC项目的影响最大,因为DEC是当时一家大型计算机公司。这项工作始于 1988 年,最初的目标是保持 32 位 VAX 架构的长期相关性。设计师们很快意识到这是不切实际的,并设计了一种新的架构,打算持续至少 25 年。因此,他们选择了 64 位寻址,以确保不会耗尽地址空间。

发布非 64 位的 Alpha 或 MIPS 竞争对手显然会产生“为什么不是 64 位?”的营销问题。问题。于是64位就成了共识。较新的 RISC-V 架构为 128 位寻址提供了一些规定,尽管尚未设计。

一个重要的细节:当前的 64 位处理器实际上无法连接 64 位的内存。他们都没有足够的地址线。这没关系。未来的实现可以提供更多的地址线。必须阻止程序员使用“备用”地址位,但这是可行的,并且操作系统可以设计为拒绝这种使用。

64 位 ARMv9-A 具有可选功能来提高安全性,这些功能使用一些“备用”高位,但它们是可选的,旨在用于目前不需要 PB 和 EB 内存的移动设备。


ctr*_*lor 16

具有 2\xe2\x81\xbf 位寄存器,允许使用整数位对寄存器中的位进行寻址:

\n

对 8 位寄存器中的一位进行寻址将需要 3 位。对 16 位寄存器中的一位进行寻址将需要 4 位。但是,寻址 12 位寄存器中的一位将需要 3.58\xe2\x80\xa6 位。您必须将其四舍五入为 4,从而浪费了 \xe2\x89\x880.4 的一点。

\n

例子

\n
    \n
  • 立即移位:移位距离存储在指令中。
  • \n
  • 立即读位:读取寄存器的一位,位号在指令中指定。
  • \n
  • 从大内存字段中读取或写入位:掩码(按位与)获取地址的高位并将它们用作字节地址,掩码(按位与)获取地址的低位并将它们用作字节地址位偏移。
  • \n
\n

我们并不总是使用寄存器来指定位。我们经常使用立即寻址(地址在指令中)。即使arm也这样做,但它没有立即寻址(在字节级别)。当我们在寄存器中拥有地址时,我们通常会处理超过 32 位的数据,因此必须对地址进行掩码以获取字节数和位数。这仅因 2 的幂而有效。

\n

  • 我想听听组装开发人员或芯片设计人员对此有何看法。我不认为寻址位是一种常见的操作,而且大多数位都被浪费了:如果你用 16 位寄存器寻址 16 位寄存器,你就浪费了 12 位,而且随着寄存器的增长,情况会变得更糟。 (12认同)
  • 为了不浪费地址空间,通常使用 8、16 或 32 个寄存器,而不是每个寄存器都是 8、16 或 32 位宽。相关的地址空间是寄存器号(在机器代码指令中占用空间,如在 MIPS 中,其中 dst、src1 和 src2 各占 5 位:http://www.cs.kzoo.edu/cs230/Resources/ MIPS/MachineXL/InstructionFormats.html),而不是位数。尽管有趣的是,MIPS 在其简单指令格式中确实为 SHAMT 字段提供了足够的空间,大多数指令不使用该字段,仅使用它作为移位量进行移位。大多数 ISA 并没有那么浪费 (2认同)
  • 好吧,是的,ARM 机器代码在大多数或所有指令中都有移位计数的空间,但这是例外,而不是规则。当 x86 机器代码确实具有立即移位计数时,它要么是 2 位(在寻址模式的 SIB 字节中用于缩放索引),要么是 8 位(屏蔽为 5 或 6),作为某些指令(如“shr”)的“imm8” /shl/bt`。通过将位索引分解为字节地址和字节内位(或字内),可以轻松地对内存中的大型位数组进行索引,这对于 2 的幂寄存器宽度来说是一个优势,尽管这一优势很小。 (2认同)

har*_*ymc 10

最常见的原因是因为计算机使用二进制系统,其中一位可以是零或一。如果计算机对位使用三进制值,那么我们就会得到 3 的幂。

关于 RAM/内存:

地址总线中的 N 个位(用于选择地址)可以对2^N字节进行寻址。每当地址位数增加到 时N+1,可寻址空间就会自动增加 2 倍。

制造商在设计中包含内存芯片时自然会使用最大地址容量,因此内存大小自然会是2的幂。

关于寄存器大小:

同样的推理也适用,因为硬件在内部可以使用其编号来寻址寄存器中的位,该编号同样采用二进制表示法。

(所有这些都只是一个假设,是对实际情况的极大简化。我相信电气工程师将能够演示为什么基于二进制逻辑的电路自然会使用幂二。正如 Intel 8086 所示,其他数字也是可能的,但制造成本可能更高。)

  • @Yorik 8086 的地址总线恰好是 20 位:如果您尝试访问像 0xFFFF:0x0100 这样的地址,您将到达物理地址 0x000F0,而不是 0x1000F0。不,它在任何意义上都不是 32 位:所有通用寄存器都是 16 位,并且这些寄存器(其中一些)用于指向内存(除了 16 位段寄存器之外)。 (11认同)
  • 正如我在另一个答案中[评论](https://superuser.com/questions/1735122/why-are-most-the-common-processors-bit-count-a-power-of-2#comment2686089_1735188),寄存器宽度是 2 的幂,与寄存器内的寻址位并没有真正的关系。除了移位指令之外,这种情况不会发生,CPU 只是将所有位提供给 ALU。寻址是我们拥有 2 的幂*数量*的寄存器的原因,以免浪费机器代码中寄存器编号的编码空间。寄存器宽度是字节大小 (8) 的倍数,为了使二进制地址数学乘法/取模便宜,我们需要 2^n 字节 (7认同)
  • 在实践中,对于 N 位物理地址空间,无论如何,至少从我记得的 VHDL 和 Verilog 设计的位来看,您将拥有 N 条独立的线路。另外,由于多种原因,大多数(我会说全部,但我确信其中存在一些奇怪的罕见情况)64 位 CPU 实际上并没有 64 位地址空间,因此真正的答案是“它们没有”。例如,对于 x64 CPU,架构限制是 52 位物理内存,实际上我认为使用了 40 位(TLB 缓存和额外的间接寻址在那里成为问题)。 (5认同)
  • @Voo:是的,当然。 x86-64 当前的页表格式将最大可能的物理地址大小限制为 52 位。我们还没有遇到这个问题,但已经很接近了。例如,[2011 年的 Westmere Xeon E7-4820](https://en.wikichip.org/wiki/intel/xeon_e7/e7-4820) 支持 44 位物理地址。 (这不仅包括 DRAM,还包括 PCIe 地址空间,以防万一。)并且 [Skylake Xeon-D](https://en.wikichip.org/wiki/intel/xeon_d/d-2191) 支持 46 位。 (这与您可以连接到单个插槽的最大 DRAM 是分开的;巨大的 RAM 需要多个插槽) (4认同)
  • @Voo:额外的“间接”(页表级别)是更宽的“虚拟”地址的缺点,例如 Ice Lake 中用于 57 位虚拟的 PML5,因此操作系统不会启用它,除非 48 位虚拟地址- 空间不够宽阔。 ([为什么在 x86-64 中虚拟地址比物理地址短 4 位(48 位与 52 位长)?](//stackoverflow.com/q/46509152))。 CPU 支持的“物理”地址宽度会在缓存标记和 TLB 中消耗额外的位,因此它会逐渐增长。我猜想是在内部线路中传递数据;在外部 DDR 内存总线上,地址被分为行/列。 (2认同)

Mad*_*Man 8

正如 RonJohn 所写,“计算机行业在 IBM 的推动下,对通用计算机的 8 位字节进行了标准化”。

之后,使用 2 倍数的幂有内部优势 - 当使用不同大小的字节集合时,它允许所有内容对齐,并允许将地址的不同位路由到不同的位置 - 例如哪个缓存行您想要的 /block/page 与缓存行/block/page 中的位置。如果使用除 2 的幂以外的任何东西,则需要进行丑陋(且缓慢)的除法。

例如,您可能有 32 或 64 位寄存器、64 或 128 位内存总线、128 位或 256 位缓存行、磁盘上的 512 字节(= 4096 位)块、内存中的 4096 字节(= 32768 位)页面,等等。只要这些都是2的幂,它们之间的边界将尽可能位于相同的位置,并且为了寻址目的,地址都按位分开,这导致硬件更简单。

例如,如果您要在其中放入 25 位或 48 位结构并希望拥有它们的数组,那么要么会浪费空间,要么最终会导致元素跨缓存行、内存页等分割。并且需要使用所有位进行除法才能确定地址位于哪个元素中。

其中的对齐部分并不像以前那样重要 - 例如,现代 Intel/AMD 芯片不会对字节级别的未对齐数据进行惩罚,但在这方面已经进行了大量的工程设计。

如果最低可寻址单元是一定数量的位,只要使用 2 的幂以上,它也可以正常工作 - 例如,如果一个字节是 7 位,则其他值将为 14, 28, 56, 112 。 …… 事实上,许多较旧的架构和一些更专业的字可寻址 CPU(如 DSP)使用不同的字大小,特别是在数据和程序存储器单独存储的情况下(哈佛架构)。

  • 如果 CPU 必须将物理地址除以 3 或 5 或某个非 2 的幂才能确定要查找的缓存线,或者双通道系统要使用哪个内存控制器,那将是一场灾难,增加一些重要关键路径的延迟。 (就像 L1d 缓存命中时间一样。)相反,我们只需接线即可通过获取位范围将地址分解为多个片段。我认为字节寻址内存是一个主要推动力;在可字寻址的机器中,奇怪的字长不是问题。 (如 24 位 DSP。) (5认同)