简体   繁体   English

旧的 DOS C 编译器是否将 double 实现为 32 位?

[英]Did old DOS C compilers implement double as 32-bit?

I'm reading Michael Abrash's Graphics Programming Black Book which is all about 3D graphics performance, so I was surprised to find that a lot of the C code there uses double instead of float .我正在阅读 Michael Abrash 的 Graphics Programming Black Book,它是关于 3D 图形性能的,所以我惊讶地发现那里的很多 C 代码使用double而不是float We're talking about early 90s computers (286, 386, Pentium) and MS-DOS C compilers, so what's the reason for using double in that era?我们谈论的是 90 年代早期的计算机(286、386、奔腾)和 MS-DOS C 编译器,那么在那个时代使用double的原因是什么? Didn't float exist or was double 's and float 's precision different than today?不存在float还是doublefloat的精度与今天不同?

In short, why double was used in performance-critical code in that era?简而言之,那个时代为什么在性能关键代码中使用double

As far as I know there was no C compiler targeting MS-DOS that used a 32-bit wide double , instead they all used a 64-bit wide double .据我所知,没有针对 MS-DOS 的 C 编译器使用 32 位宽的double ,而是它们都使用了 64 位宽的double This was certainly the case by the early 90's.到 90 年代初,情况确实如此。 Based on quick read of the "Floating Point for Real-Time 3D" chapter of the book, it appears the Michael Abrash thought that floating-point math of any precision was too slow on anything less than a Pentium CPU.基于对本书“实时 3D 浮点”一章的快速阅读,Michael Abrash 似乎认为任何精度的浮点数学在低于 Pentium CPU 的任何东西上都太慢了。 Either the floating-point code you're looking was intended for Pentium CPUs or it was used on a non-critical path where performance doesn't matter.您正在寻找的浮点代码要么是为奔腾 CPU 设计的,要么是用于性能无关紧要的非关键路径。 For performance critical code meant for earlier CPUs, Abrash implies that he would've used fixed-point arithmetic instead.对于适用于早期 CPU 的性能关键代码,Abrash 暗示他会使用定点算法来代替。

In a lot of cases using float instead of double wouldn't have actually made much difference.在很多情况下,使用float而不是double实际上不会有太大区别。 There's a few reasons.有几个原因。 First, if you don't have an x87 FPU (floating-point unit) installed (a separate chip before the '486), using less precision wouldn't improve performance enough to make software emulated floating-point arithmetic fast enough to be useful for game.首先,如果您没有安装x87 FPU(浮点单元) ('486 之前的单独芯片),则使用较低的精度不会提高性能足以使软件模拟浮点算法足够快以供使用为游戏。 The second is that the performance of most x87 FPU operations wasn't actually affected by precision.第二个是大多数 x87 FPU 操作的性能实际上不受精度影响。 On a Pentium CPU only division was faster if performed at a narrower precision.在 Pentium CPU 上,如果以较窄的精度执行,则只有除法会更快。 For earlier x87 FPUs I'm not sure precision affected division, though it could affect the performance of multiplication on the 80387. On all x87 FPUs addition would've been the same speed regardless of precision.对于早期的 x87 FPU,我不确定精度会影响除法,但它可能会影响 80387 上的乘法性能。在所有 x87 FPU 上,无论精度如何,加法的速度都是相同的。

The third is that the specific C data type used, whether a 32-bit float , the 64-bit double , or even the 80-bit long double that many compilers supported, didn't actually affect the precision the FPU used during calculations.第三是所使用的特定 C 数据类型,无论是 32 位float 、64 位double还是许多编译器支持的 80 位long double ,实际上并没有影响 FPU 在计算过程中使用的精度。 This is because the FPU didn't have different instructions (or encodings) for the three different precisions it supported.这是因为 FPU 对于它支持的三种不同精度没有不同的指令(或编码)。 There was no way to tell it perform a float addition or a double divide.没有办法告诉它执行float加法或double除法。 Instead it performed all arithmetic at a given precision that was set in the FPU's control register.相反,它以 FPU 控制寄存器中设置的给定精度执行所有算术运算。 (Or more accurately stated, it performed arithmetic as if using infinite precision and then rounding the result to the set precision.) While it would've been possible to change this register every time a floating-point instruction is used, this would cause massive decrease in performance, so compilers never did this. (或者更准确地说,它执行算术就像使用无限精度,然后将结果四舍五入到设置的精度。)虽然每次使用浮点指令时都可以更改此寄存器,但这会导致大量性能下降,所以编译器从来没有这样做过。 Instead they just set it to either 80-bit or 64-bit precision at program startup and left it that way.相反,他们只是在程序启动时将其设置为 80 位或 64 位精度,然后保持这种方式。

Now it was actually a common technique for 3D games to set the FPU to single-precision.现在,将 FPU 设置为单精度实际上是 3D 游戏的常用技术。 This meant floating-point arithmetic, whether using double or float types, would be performed using single-precision arithmetic.这意味着浮点算术,无论是使用double还是float类型,都将使用单精度算术来执行。 While this would end up only affecting the performance of floating-point divides, 3D graphics programming tends to do a lot divisions in critical code (eg. perspective divides), so this could have a significant performance improvement.虽然这最终只会影响浮点除法的性能,但 3D 图形编程往往会在关键代码(例如透视除法)中进行大量除法,因此这可能会显着提高性能。

There is however one way that using float instead of double could improve performance, and that's simply because a float takes up half the space of a double .然而,有一种方法可以使用float而不是double可以提高性能,这仅仅是因为float占用了double一半空间。 If you have a lot of floating-point values then having to read and write half as much memory can make a significant difference in performance.如果您有很多浮点值,那么必须读写一半的内存会对性能产生显着影响。 However, on Pentium or earlier PCs this wouldn't result in the huge performance difference it would today.但是,在 Pentium 或更早的 PC 上,这不会导致今天的巨大性能差异。 The gap between CPU speed and RAM speed wasn't as wide back then, and floating-point performance was a fair bit slower.那时 CPU 速度和 RAM 速度之间的差距并没有那么大,浮点性能要慢一些。 Still, it would be a worth while optimization if the extra precision isn't needed, as is usually the case in games.尽管如此,如果不需要额外的精度,这将是值得的优化,这在游戏中通常是这种情况。

Note that modern x86 C compilers don't normally use x87 FPU instructions for floating-point arithmetic, instead they use scalar SSE instructions, which unlike the x87 instructions, do come in single- and double-precision versions.请注意,现代 x86 C 编译器通常不使用 x87 FPU 指令进行浮点运算,而是使用标量 SSE 指令,与 x87 指令不同,它有单精度和双精度版本。 (But no 80-bit wide extended-precision versions.) Except for division, this doesn't make any performance difference, but does mean that results are always truncated to float or double precision after every operation. (但没有 80 位宽的扩展精度版本。)除除法外,这不会产生任何性能差异,但确实意味着每次操作后结果总是被截断为floatdouble精度。 When doing math on the x87 FPU this truncation would only happen when the result was written to memory.在 x87 FPU 上进行数学运算时,这种截断只会在结果写入内存时发生。 This means SSE floating-point code has now has predictable results, while x87 FPU code had unpredictable results because it was in general hard to predict when the compiler would need to spill a floating-point register into memory to make room for something else.这意味着 SSE 浮点代码现在具有可预测的结果,而 x87 FPU 代码具有不可预测的结果,因为通常很难预测编译器何时需要将浮点寄存器溢出到内存中以便为其他内容腾出空间。

So basically using float instead of double wouldn't have made a big performance difference except when storing floating-point values in a big array or other large data structure in memory.所以基本上使用float而不是double不会产生很大的性能差异,除非将浮点值存储在内存中的大数组或其他大型数据结构中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM