标准委员会关心的异国build筑
我知道,C和C ++标准留下了语言实现的许多方面 – 定义只是因为如果有一个具有其他特性的体系结构,编写一个标准的兼容编译器是非常困难或不可能的。
我知道40年前任何一台电脑都有自己独特的规格。 但是,我不知道今天使用的任何架构:
CHAR_BIT != 8
-
signed
是不是二补(我听说Java有这个问题)。 - 浮点不符合IEEE 754(编辑:我的意思是“不在IEEE 754二进制编码”)。
我问的原因是,我经常向人们解释,C ++没有强制要求像固定大小types那样的其他低级方面。 这很好,因为与其他语言不同,它使得你的代码在正确使用的时候是可移植的(编辑:因为它可以移植到更多的架构,而不需要仿真机器的低级方面,比如像符号+量级架构上的二进制补码algorithm) 。 但我感到不好意思,我不能指出任何特定的架构。
所以问题是:什么样的架构展现出上述特性?
† uint*_t
s是可选的。
看看这个
Unisys ClearPath Dorado服务器
为尚未迁移Univac软件的用户提供向后兼容性。
关键点:
- 36位字
-
CHAR_BIT == 9
- 补充
- 72位非IEEE浮点
- 单独的代码和数据的地址空间
- 文字处理
- 没有专用的堆栈指针
不知道他们是否提供了一个C ++编译器,但他们可以 。
现在,他们的C手册的最新版本的链接已经浮出水面:
Unisys C编译器编程参考手册
4.5节有一个9,18,36和72位的数据types表。
你的假设对于大型机没有任何假设。 对于初学者来说,我不知道使用IEEE 754的大型机:IBM使用16位浮点,而Unisys两个主机都使用8位。Unisys机器在其他许多方面都有点特别:Bo提到了2200架构,但是MPS架构更加陌生:48位标记的单词。 (这个单词是否是一个指针取决于这个单词中的一个位)。数字表示的devise使得浮点和积分算术之间没有真正的区别:浮点数为8; 它不需要标准化,并且不像我所看到的每一个浮点,它都把尾数放在尾数的右边,而不是左边,并且对指数(除了尾数)使用有符号的幅度。 由于积分浮点值具有(或可以具有)与有符号整数相同的比特表示的结果。 而且没有浮点运算指令:如果两个值的指数均为0,则指令进行积分运算,否则进行浮点运算。 (体系结构中标记哲学的延续。)这意味着虽然int
可能占用48位,但其中8个必须为0,否则该值不会被视为整数。
在浮点实现中完全符合IEEE 754标准是罕见的。 在这方面弱化规范允许进行大量的优化。
例如x87和SSE之间的子范式支持不同。
像源代码中分离的乘法和加法融合的优化也稍微改变了结果,但在某些体系结构上却是不错的优化。
或者在x86上,严格的IEEE兼容性可能要求设置某些标志,或者在浮点寄存器和正常内存之间进行额外的传输,以强制它使用指定的浮点types而不是其内部80位浮点数。
有些平台根本没有硬件浮点数,因此需要用软件模拟它们。 而IEEE 754的一些要求在软件中实现可能是昂贵的。 特别是舍入规则可能是一个问题。
我的结论是,你不需要外来的架构来进入情况,你并不总是想保证严格的IEEE符合性。 由于这个原因,很less有编程语言保证严格的IEEE标准。
我发现这个链接列出了一些 CHAR_BIT != 8
。 他们包括
一些TI DSP的
CHAR_BIT == 16
BlueCore-5芯片(来自Cambridge Silicon Radio的蓝牙芯片),其具有
CHAR_BIT == 16
。
当然还有一个关于堆栈溢出的问题: 什么平台除了8位字符以外还有其他的东西
至于非二进制补码系统,在comp.lang.c ++。moderated上有一个有趣的读法。 总结:有平台有补码或符号和大小的表示。
我很确定VAX系统仍在使用中。 他们不支持IEEE浮点; 他们使用自己的格式。 Alpha支持VAX和IEEE浮点格式。
像T90这样的Crayvector机也有它们自己的浮点格式,虽然更新的Cray系统使用IEEE。 (我使用的T90是在几年前退役的,我不知道是否还在使用中)
T90也有指针和整数的一些有趣的表示。 本地地址只能指向一个64位的字。 C和C ++编译器有CHAR_BIT == 8(因为它运行的是Unicos,Unix的味道,必须与其他系统互操作),但本机地址只能指向64位字。 所有的字节级操作都是由编译器合成的, void*
或char*
在字的高3位中存储了一个字节偏移量。 我认为一些整数types有填充位。
IBM大型机是另一个例子。
另一方面,这些特定的系统不一定排除对语言标准的改变。 Cray没有performance出将C编译器升级到C99的特别兴趣; 大概是应用于C ++编译器的相同的东西。 收紧托pipe实现的需求可能是合理的,比如需要CHAR_BIT == 8,IEEE格式的浮点(如果不是完整的语义),2的补码不带有填充位,用于带符号的整数。 旧系统可以继续支持早期的语言标准(当C99出来时,C90并不会死掉),对于像DSP这样的独立实现(embedded式系统),要求可能更宽松。
另一方面, 未来的系统可能有充分的理由去做今天被认为是异域的事情。
CHAR_BITS
根据海湾合作委员会的源代码:
对于1750a , dsp16xx架构, CHAR_BIT
是16
位。
CHAR_BIT
是dsp56k架构的24
位。
CHAR_BIT
是c4x架构的32
位。
你可以很容易地find更多的做:
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
witch也可以禁止零符号保留)。
直到最近,IEEE 754二进制表示在GPU上才不常见,参见GPU浮点偏执狂 。
编辑:在评论中提出了一个问题:GPU浮点是否与通常的计算机编程相关,与graphics无关。 当然好! 今天工业计算的最高性能的东西是在GPU上完成的; 该列表包括人工智能,数据挖掘,neural network,物理模拟,天气预报等等。 评论中的链接之一显示了为什么:GPU的浮点优势的一个数量级 。
另一件我想补充的,与OP问题更为相关的是:10年前,当GPU浮点数不是IEEE以及当今的OpenCL或CUDA等API没有对GPU进行编程时,人们做了什么? 信不信由你,早期的GPU计算先驱们设法对GPU进行编程,而不需要API来做到这一点 ! 我在公司遇见他们中的一个。 这就是他所做的:他将需要计算的数据编码为像素,代表他正在处理的值,然后使用OpenGL执行他需要的操作(例如“高斯模糊”来表示具有正态分布的卷积等等),并将结果图像解码成结果数组。 这还是比使用CPU更快!
像这样的事情促使NVidia最终使其内部数据二进制与IEEE兼容,并引入了面向计算而不是image processing的API。