Delphi 检查精度的FPU指令
使用fldcw指令,可以将FPU单元的精度更改为24位或更多位。然而,在做了一些测试之后,我开始认为实际上很少有x87操作使用这种设置 我还没有测试所有的操作,但是到目前为止,在这个测试机器上,看起来只有fdiv和fsqrt在选定的精度下停止计算,并且所有其他操作(fadd fsub fmul…)总是计算完全扩展精度 如果是这样的话,我希望是这样的,因为这两条指令(fdiv和fsqrt)比大多数其他x87 FPU指令要慢得多,所以当精度足够低时,可以加快速度,但实际上,我只是想知道这是否一直都是这样,或者这是我的测试机器中使用的最新处理器的一个怪癖 编辑:下面是显示它的delphi代码Delphi 检查精度的FPU指令,delphi,x86,fpu,x87,Delphi,X86,Fpu,X87,使用fldcw指令,可以将FPU单元的精度更改为24位或更多位。然而,在做了一些测试之后,我开始认为实际上很少有x87操作使用这种设置 我还没有测试所有的操作,但是到目前为止,在这个测试机器上,看起来只有fdiv和fsqrt在选定的精度下停止计算,并且所有其他操作(fadd fsub fmul…)总是计算完全扩展精度 如果是这样的话,我希望是这样的,因为这两条指令(fdiv和fsqrt)比大多数其他x87 FPU指令要慢得多,所以当精度足够低时,可以加快速度,但实际上,我只是想知道这是否一直都是
program Project1;
uses
windows,dialogs,sysutils;
{$R *.res}
const
test_mul:single=1234567890.0987654321;
var
i:longint;
s:single absolute i;
s1,s2,s3:single;
procedure test_24;
asm
mov word([esp-2]),$103f // 24bit precision, trunc
fldcw word([esp-2])
fld [s]
fmul [test_mul]
fstp [s1]
end;
procedure test_53;
asm
mov word([esp-2]),$123f // 53bit precision, trunc
fldcw word([esp-2])
fld [s]
fmul [test_mul]
fstp [s2]
end;
procedure test_64;
asm
mov word([esp-2]),$133f // 64bit precision, trunc
fldcw word([esp-2])
fld [s]
fmul [test_mul]
fstp [s3]
end;
begin
i:=0;
repeat
test_24;
test_53;
test_64;
if (s1<>s2) or (s2<>s3) then begin
showmessage('Error at step:'+inttostr(i));
break;
end;
inc(i);
until i=0;
showmessage('No difference found between precisions');
end.
程序项目1;
使用
窗口、对话框、系统工具;
{$R*.res}
常数
测试单元:单个=1234567890.0987654321;
变量
i:长型;
s:单绝对i;
s1、s2、s3:单一;
程序测试24;
asm
mov字([esp-2]),103f美元//24位精度,trunc
fldcw字([esp-2])
佛罗里达州[南]
fmul[测试工具]
fstp[s1]
结束;
程序测试53;
asm
mov字([esp-2]),$123f//53位精度,trunc
fldcw字([esp-2])
佛罗里达州[南]
fmul[测试工具]
fstp[s2]
结束;
程序测试64;
asm
mov字([esp-2]),133f//64位精度,trunc
fldcw字([esp-2])
佛罗里达州[南]
fmul[测试工具]
fstp[s3]
结束;
开始
i:=0;
重复
测试24;
测试单元53;
测试64;
如果(s1s2)或(s2s3),则开始
showmessage('步骤出错'+inttostr(i));
打破
结束;
公司(一);
直到i=0;
showmessage(“精度之间未发现差异”);
结束。
edit2:假警报,我错了,我存储为单存储而不是扩展存储,因此无法捕捉差异,这里有一个固定测试,感谢hans passant捕捉到我的错误:
program Project1;
uses
windows,dialogs,sysutils;
{$R *.res}
const
test_mul:single=1234567890.0987654321;
var
i:longint;
errors:cardinal;
s:single absolute i;
s1,s2,s3:extended;
procedure test_24;
asm
mov word([esp-2]),$103f // 24bit precision, trunc
fldcw word([esp-2])
fld [s]
fmul [test_mul]
fstp [s1]
end;
procedure test_53;
asm
mov word([esp-2]),$123f // 53bit precision, trunc
fldcw word([esp-2])
fld [s]
fmul [test_mul]
fstp [s2]
end;
procedure test_64;
asm
mov word([esp-2]),$133f // 64bit precision, trunc
fldcw word([esp-2])
fld [s]
fmul [test_mul]
fstp [s3]
end;
begin
errors:=0;
i:=0;
repeat
test_24;
test_53;
test_64;
if (s1<>s2) or (s2<>s3) then begin
inc(errors);
end;
inc(i);
until i=0;
showmessage('Number of differences between precisions: '+inttostr(errors));
end.
程序项目1;
使用
窗口、对话框、系统工具;
{$R*.res}
常数
测试单元:单个=1234567890.0987654321;
变量
i:长型;
错误:基数;
s:单绝对i;
s1,s2,s3:扩展;
程序测试24;
asm
mov字([esp-2]),103f美元//24位精度,trunc
fldcw字([esp-2])
佛罗里达州[南]
fmul[测试工具]
fstp[s1]
结束;
程序测试53;
asm
mov字([esp-2]),$123f//53位精度,trunc
fldcw字([esp-2])
佛罗里达州[南]
fmul[测试工具]
fstp[s2]
结束;
程序测试64;
asm
mov字([esp-2]),133f//64位精度,trunc
fldcw字([esp-2])
佛罗里达州[南]
fmul[测试工具]
fstp[s3]
结束;
开始
误差:=0;
i:=0;
重复
测试24;
测试单元53;
测试64;
如果(s1s2)或(s2s3),则开始
inc(错误);
结束;
公司(一);
直到i=0;
showmessage('精度之间的差异数:'+inttostr(错误));
结束。
您能告诉我们复制此(汇编代码,…)的方法吗?请注意,有些库可能会“有帮助地”为您重置浮点控制字。哦,我刚刚编写了直接汇编程序代码,没有令人惊讶的代码。我将在5-10分钟内编辑一些代码,我将完成另一个问题的输入。当然,在现代处理器上,你不能使一条指令只占用一个周期的速度更快。@HansPassant存在双舍入的问题,这会使计算达到全精度适得其反,即使处理器在一个周期内有足够的时间进行计算,甚至更多。不确定代码试图证明什么,但是如果您想看到差异,那么必须将结果存储在双精度变量中。