【问题标题】:In computers 32-bit or 64-bit processors are used, why not 40-bit or other numbers?在计算机中使用 32 位或 64 位处理器,为什么不使用 40 位或其他数字?
【发布时间】:2015-09-14 22:54:57
【问题描述】:

例如,对于 32 位处理器,一个字的长度为 4 字节。是否也可以使用5字节字或其他?

【问题讨论】:

  • 32 和 64 是 2 的幂。32 = 2^5 64 = 2 ^ 6。“下一个比特”可能是 128 (2 ^ 7)。
  • 是的,但为什么这是必要的,深度有 1 和 0。
  • 这不是绝对必要的。但有几个原因。除了 32=100000b 和 64=1000000b 是二进制的“好”数字之外,2 的幂还有很多除数(当然,也是 2 的幂)。在这里更深入会导致有关en.wikipedia.org/wiki/Arithmetic_logic_unit 的设计和内存/缓存层次结构的详细信息可能超出此处的答案范围(尽管仍然可以 try 给出一个好的答案 - 我不敢……)
  • 计算机设计师喜欢 2 的幂,它使二进制电路设计更加简单。 5 不是一个快乐的数字。不要让你的泡沫破灭,但最流行的 64 位处理器实际上使用 40 位作为地址总线 :)

标签: 32bit-64bit cpu-architecture rationale word-size


【解决方案1】:

是否也可以使用5字节字或其他

是的。您甚至可以通过bit fields 仅使用几位而不是整个字节/字。从技术上讲,编译器可以在任何架构上支持任何整数大小,例如 16 位计算机上的 12 位、30 位或 96 位 int。事实上,Clang 刚刚为具有任意位宽的整数提供了一个新的扩展,称为_ExtInt。另请参阅

为什么不是 40 位或其他数字?

性能会受到很多的影响。我们需要更多指令来处理非原生整数大小。如果大小小于一个字,则编译器需要发出按位指令来屏蔽剩余的位。在相反的情况下,我们需要多个指令来处理多个单词

另一个重要的事情是misalignment。当变量的地址是其大小的倍数或至少是数据总线宽度/字大小的倍数时,现代 CPU 的工作效率更高。使用奇数大小的变量很尴尬


也就是说,存在许多具有 40 位类型的 32 位架构,例如 TI C6000TI C5500 DSP

long

  • 40 位或 C6000 COFF 5 字节

[...] 和 C5500 具有 40 位 long long

C89 Support in TI Compilers

这是因为这些 DSP 有一个特殊的 40 位累加器,允许将 32 位数字相加 256 次而不会溢出。但是为什么不直接使用 64 位累加器呢?这将需要更大的 ALU,需要更多的功率并且运行速度更慢(因为更大的区域意味着硬件组件之间的距离更长,并且在大数字上运行比在较小的数字上运行慢),这在为性能而设计的 DSP 中是不可接受的(可能还有力量)

... 例如,德州仪器公司的 TMS320C6000,一个 DSP 处理器,使用 32 位表示类型int,使用 40 位表示类型long(这种选择并不少见)。那些使用 24 位来表示类型int 的处理器(通常是 DSP)通常使用 48 位来表示类型long。在 32/64 位整数类型表示不具成本效益的应用需求中,可以使用 24/48 位整数类型表示。

The New C Standard (Excerpted material): An Economic and Cultural Commentary

事实上,40 位 int 在 DSP 中很常见(其他示例为 BlackfinSHARC)。 SHARC 甚至还有一个 80 位的累加器,所以你可以添加很多 64 位的值而不用担心溢出


但您不需要特殊的架构或特殊的编译器支持。如果您确实需要,您仍然可以使用 40 位变量,例如,当您使用一个巨大的数组时,其中 64 位整数会使其太大而无法放入主内存,而较少的项目会适合缓存。最简单的方法是禁用与#pragma pack__attribute__((packed)) 的对齐

struct int40_t {
    int64_t : 40;
} __attribute__((packed));
int40_t myArray[200] __attribute__((packed));

或从一个简单的字符数组中访问值(基于cmm's solution

unsigned char _5byteInts[5*size+3];  // +3 avoids overfetch of last element

int64_t get5byteInt(size_t index)
{
    int64_t v = 0;
    memcpy(&v, &_5byteInts[index*5], 5);        // little endian
    return (v << 24) >> 24;
}

void set5byteInt(size_t index, int64_t value)
{
    memcpy(&_5byteInts[index*5], &value, 5);    // little endian
}

但是这些会导致在没有未对齐访问的架构上性能不佳。您可以将四个 40 位整数打包到一个 20 字节的结构中以更好地对齐

struct four_int40s {
    uint32_t low[4];
    uint8_t hi[4];
};

【讨论】:

  • 问题是询问硬件本身支持的大小。 10 字节 x87 FP 将是一个示例,但不是 ISA 上 40 位整数的软件实现,例如 x86,具有 32 位和 64 位本机操作数大小。即它在问为什么没有 40 位 机器,而不是 C 类型。在这样的机器上,假设 CHAR_BIT=10 或(不太可能)对齐以 5 个八位字节(字长)的倍数工作,则 40 位字的数组都可以自然对齐。或者那个 CHAR_BIT=40 并且它只能是字可寻址的。
【解决方案2】:

从历史上看,有一些计算机的字长不是 2 的幂,例如 Table of word sizes。然而,最终人们发现当地址大小是 2 的幂时,地址算术更容易实现。

考虑一个操作,例如“向前跳 14 个单词”。如果字长是 2 的幂,例如 64,则电路需要将数字 14 移动 log(64)/log(2)=6 并添加到 ip,这可以在 1 个周期内轻松完成。但是,如果字长为 36,如 IBM 701,则数字 14 必须乘以 36,这将花费更多周期。鉴于将整数乘以字长是一种非常常见的操作,因此速度会显着下降。

【讨论】:

  • 我试过了,但不清楚。假设我有 4 位地址,并且一个字的长度为 4 位。我想跳 2 个字,2&lt;&lt;log(4)/log(2)=8 相当于 1000 将添加到 ip 中。我的地址是这样的:0000 0001 0010 0011 0100 ...0000 跳两个字应该落在0011 但根据公式它是1000
  • @rneha725,你说得对,我想的是位而不是字节。如果您的寻址是 8 位字节,就像当今大多数计算机一样,您必须将字长除以字节大小。
  • 例如,40 位字可能使用 10 位字节。或者只有字可寻址。是的,正如你所说,字长应该是字节大小的 2 次方。
猜你喜欢
  • 1970-01-01
  • 2012-01-12
  • 2010-10-26
  • 2012-06-06
  • 2015-04-02
  • 2015-05-21
  • 2012-10-26
  • 2011-02-05
  • 1970-01-01
相关资源
最近更新 更多