标准委员会关心的异国情调的架构

我知道 C 和 C + + 标准留下了语言实现的许多方面——定义它们仅仅是因为如果有一个具有其他特征的体系结构,就很难或不可能为它编写一个符合标准的编译器。

我知道40年前任何计算机都有自己独特的规格。然而,我不知道今天还有哪种架构可以用来:

  • CHAR_BIT != 8
  • signed不是2的补充(我听说 Java 在这个问题上有问题)。
  • 浮点数不兼容 IEEE754(编辑: 我的意思是“不在 IEEE754二进制编码中”)。

我问这个问题的原因是,我经常向人们解释,C + + 不强制任何其他低级方面,比如固定大小的类型 ,这很好。它之所以好,是因为它不同于“其他语言”,当正确使用时,它使你的代码具有可移植性(编辑: 因为它可以移植到更多的体系结构,而不需要模拟机器的低层方面,例如符号 + 数量级体系结构上的2的补数算法)。但是我感觉很糟糕,因为我自己不能指出任何具体的建筑。

因此,问题是: 哪些体系结构展示了上述属性?

? uint*_ts 是可选的。

15365 次浏览

完全符合 IEEE 754标准在浮点实现中很少见,在这方面削弱规范允许进行大量优化。

例如,x87和 SSE 之间的子规范支持是不同的。

像融合乘法和加法这样的优化在源代码中是分开的,它们也会稍微改变结果,但是对于某些架构来说是很好的优化。

或者在 x86上严格遵循 IEEE 可能需要设置某些标志,或者在浮点寄存器和普通内存之间进行额外的传输,以迫使它使用指定的浮点类型,而不是其内部的80位浮点类型。

有些平台根本没有硬件浮点,因此需要在软件中模拟它们。而且 IEEE754的一些需求在软件中实现起来可能会很昂贵。特别是舍入规则可能是个问题。

我的结论是,如果您不总是想要保证严格遵守 IEEE,那么您就不需要特殊的体系结构来处理这种情况。出于这个原因,很少有编程语言能够保证严格遵守 IEEE。

我在 CHAR_BIT != 8的地方找到了 这个链接列出了一些系统它们包括

一些 TI DSP 有 CHAR_BIT == 16

BlueCore-5芯片(蓝牙) 其中包含 < code > CHAR _ BIT = = 16 .

当然,对于 Stack Overflow 还有一个问题: 什么平台除了8位 char 之外还有其他东西

至于非二补体系统,有一个有趣的阅读 C + + 。主持人总结: 有一些平台具有自己的补语或符号和量值表示

看看这个

Unisys ClearPath Dorado 服务器

为尚未迁移所有 Univac 软件的用户提供向下兼容。

要点:

  • 36位单词
  • CHAR_BIT == 9
  • 互相补充
  • 72位非 IEEE 浮点数
  • 代码和数据的独立地址空间
  • 只字片语
  • 没有专用的堆栈指针

虽然不知道他们是否提供了 C + + 编译器,但是他们提供了 可以


现在,他们的 C 手册最新版本的一个链接浮出水面:

编译程序参考手册

第4.5节有一个包含9、18、36和72位数据类型的表。

size and range of data types in USC C compiler

你的假设都不适用于大型机,首先,我不知道 使用 IEEE 754的大型机: IBM 使用基于16的浮点数,并且 优利系统的两台大型机都使用8进制。优利系统的机器有点 在许多其他方面很特别: 薄提到了2200年的建筑, 但是 MPS 架构更加奇怪: 48位标记单词。 (单词是否是指针取决于单词中的位。) 而数值表示的设计使得不存在实数 浮点数和积分算术之间的区别: 浮点数 点是基数8; 它不需要标准化,并且不像每个 我看到的另一个浮点数,它把小数放在 尾数,而不是左边,并且使用符号大小表示 指数(除尾数外) 整数浮点值具有(或可以具有)完全相同的位 表示为一个有符号的数量级整数。并且没有浮点数 点算术指令: 如果两个值的指数为 都为0时,指令执行积分算术,否则,指令执行积分算术 浮点数算术 这意味着 int可能占据48位,而 int占据8位 它们的值必须为0,否则该值不会被视为整数。

我相当肯定 VAX 系统仍在使用。它们不支持 IEEE 浮点数; 它们使用自己的格式。Alpha 同时支持 VAX 和 IEEE 浮点格式。

Cray 矢量机,如 T90,也有自己的浮点格式,尽管较新的 Cray 系统使用 IEEE。(我使用的 T90几年前就退役了,我不知道是否还有正在使用的。)

T90还有一些关于指针和整数的有趣表示。本机地址只能指向64位单词。C 和 C + + 编译器的 CHAR _ BIT = = 8(这是必要的,因为它运行 Unicos,Unix 的一种风格,并且必须与其他系统进行互操作) ,但是本机地址只能指向一个64位的单词。所有字节级操作都由编译器合成,void*char*将字节偏移量存储在单词的高阶3位中。我认为有些整数类型有填充位。

IBM 大型机是另一个例子。

另一方面,这些特殊的系统不需要 必须的来排除对语言标准的改变。Cray 对于将其 C 编译器升级到 C99没有表现出任何特别的兴趣; 大概对于 C + + 编译器也是如此。收紧对托管实现的要求是合理的,比如要求 CHAR _ BIT = = 8、 IEEE 格式浮点数(如果不是完整的语义的话)和2的补数(如果没有符号整数的填充位)。旧系统可以继续支持早期的语言标准(C99出现时,C90还没有消亡) ,而且对于独立实现(嵌入式系统)(如 DSP)的要求可以更宽松。

另一方面,未来系统可能有很好的理由去做今天被认为是异国情调的事情。

CHAR _ Bits

根据 GCC源代码:

CHAR_BIT16位,用于 1750aDsp16xx架构。
CHAR_BIT24位,用于 Dsp56k体系结构。
CHAR_BIT32位,用于 C4x体系结构。

你可以通过以下方法轻松地找到更多:

find $GCC_SOURCE_TREE -type f | xargs grep "#define CHAR_TYPE_SIZE"

或者

find $GCC_SOURCE_TREE -type f | xargs grep "#define BITS_PER_UNIT"

如果适当定义了 CHAR_TYPE_SIZE

符合 IEEE 754标准

如果目标体系结构不支持浮点指令,则 GCC可能会生成软件回退,这在默认情况下是不符合标准的。不仅如此,还可以使用特殊选项(如 -funsafe-math-optimizations开关也禁用对零进行符号保存)。

直到最近,IEEE 754二进制表示在 GPU 上还很少见,参见 浮点偏执

编辑: 在评论中提出了一个问题: GPU 浮点数是否与通常的计算机编程相关,与图形无关。太好了!目前工业上大多数高性能的计算都是在 GPU 上完成的,这个列表包括人工智能、数据挖掘、神经网络、物理模拟、天气预报等等。评论中的一个链接说明了原因: GPU 的一个 数量级浮点优势。

另一件我想补充的事情,这与 OP 的问题更相关: 10-15年前,当 GPU 浮点不是 IEEE,当没有像今天的 OpenCL 或 CUDA 这样的 API 来编程 GPU 的时候,人们做了什么?信不信由你,早期的 GPU 计算先驱设法 没有 API 的 GPU 程序!我在公司认识了一个。他是这样做的: 他把需要计算的数据编码成图像,用像素表示他正在处理的值,然后使用 OpenGL 执行他需要的操作(比如“高斯模糊”表示正态分布的卷积,等等) ,然后把得到的图像解码回一个结果数组。这仍然比使用 CPU 快!

这样的事情促使 NVidia 最终使他们的内部数据二进制兼容 IEEE,并引入面向计算而不是图像操作的 API。