如何使用 gnu gcc 标志 -mpc32、-mpc64 和 -mpc80?
Posted
技术标签:
【中文标题】如何使用 gnu gcc 标志 -mpc32、-mpc64 和 -mpc80?【英文标题】:How to use gnu gcc flag -mpc32, -mpc64 and -mpc80? 【发布时间】:2020-01-24 10:26:36 【问题描述】:我从GNU GCC compiler Manual 获得了这些 GCC 标志。但是当我尝试使用这些标志(-mpc32
、-mpc64
和-mpc80
)时,我无法观察到这种行为。因此,我需要有关如何通过示例代码使用这些标志的帮助。
我试过的示例代码:test.cpp
#include<stdio.h>
#include<iomanip>
#include<math.h>
int main()
double weight = 1.0f;
double roiSize = 137.142364501953125f;
double thresholdValue = 5400.0f;
double alpha = weight / (roiSize * thresholdValue * thresholdValue);
std::cout<<std::setprecision(100)<<"alpha = "<<f<<std::endl;
double test = pow(roiSize, 10);
std::cout<<std::setprecision(100)<<"alpha = "<<f<<std::endl;
编译选项:
g++ -mpc32 test.cpp
g++ -mpc64 test.cpp
g++ -mpc80 test.cpp
【问题讨论】:
更新了我测试的代码。 【参考方案1】:测试不同 x87 精度的最简单方法可能是使用long double
,它在 x86 目标上是 80 位 x87 类型。 (在 Windows 上 long double = double 除外)。
long double
的另一个优点是您根本不需要使用-m32
进行编译以使其使用 x87。 (-m64
的默认值是 -mfpmath=sse
;双精度和浮点数学运算将在 XMM 寄存器中以类型宽度完成,不会扩大到 x87 内部精度。但 long double
将始终使用 x87,因为 SSE/SSE2 不能做80位)。 TL:DR:在使用 gcc -mpc32 foo.c
构建的普通 64 位系统上,-mpc32
不会对 double
变量的数学产生任何影响,因为它甚至不使用旧版 x87 FPU。
顺便说一句,这个测试用例也依赖于使用默认的-O0
编译,否则编译时会发生持续传播。 (这不太可能尊重-mpc32
。)
137.142364501953125f
是一个float
常量,在用作double
的初始化程序之前四舍五入为浮点数。因此,尽管存储为double
,但您的起始值都四舍五入到最接近的float
。不过,我认为除法并不准确,因此您仍然会四舍五入。
我假设这些选项只是在启动时设置 x87 精度。 MSVC 的 CRT 启动代码显然做了类似的事情,默认设置为 64 位精度(53 位尾数,如double
,不是全精度)。请参阅 Bruce Dawson 的 Intermediate Floating-Point Precision 文章; FP 系列文章之一。 Index in this one.
您可以查看编译器生成的 asm 以了解它如何进行 FP 数学运算:使用 fld
/ fmul
/ fstp
是 x87 并且会受到 x87 控制字寄存器中设置的 x87 精度的影响。
movsd
/mulsd
是SSE2,精度由指令设置;没有状态/控制位可以覆盖它。 (在 MXCSR 中只能更改舍入模式,以及处理次正规。)
【讨论】:
以上是关于如何使用 gnu gcc 标志 -mpc32、-mpc64 和 -mpc80?的主要内容,如果未能解决你的问题,请参考以下文章