Visual C ++可以发出C4738 warning:
将32位浮点数存储在内存中,可能会导致性能下降
用于将32位float
存储在内存中而不是存储在寄存器中的情况。
说明进一步说明使用double
可以解决问题。我不明白为什么后者是真的。
为什么在内存中存储float
会导致性能下降并且存储double
不会?
答案 0 :(得分:8)
警告结合了两个问题:
使用double解决第二个问题(至少部分地,64位仍然不如80位精确),但对可能的性能损失没有影响。这就是警告解释提到两种补救措施的原因:
要解决此警告并避免舍入,请使用/ fp:fast或 使用双打而不是花车。
要解决此警告并避免用完寄存器,请更改 计算顺序和修改你使用内联
答案 1 :(得分:3)
虽然我不能100%确定原因,但这是我的猜测。
在x86上编译并且未启用SSE2时,编译器必须将x87 FP堆栈用于所有浮点寄存器。在MSVC上,默认情况下,FP模式设置为53位精度舍入。 (我想。我不是百分百肯定的。)
因此,在FP-stack上完成的所有操作都是双精度的。
但是,当某些内容被转换为float
时,精度需要舍入为单精度。唯一的方法是通过4字节内存操作数上的fstp
指令将其存储到内存中 - 并重新加载它。
让我们看看您链接到的C4738 warning page上的示例:
float func(float f)
{
return f;
}
int main()
{
extern float f, f1, f2;
double d = 0.0;
f1 = func(d);
f2 = (float) d;
f = f1 + f2; // C4738
printf_s("%f\n", f);
}
当您致电func()
时,d
可能存储在x87注册表中。但是,对func()
的调用要求将精度降低到单精度。这将导致d
舍入/存储到内存。然后在f = f1 + f2;
行重新加载并重新提升为双精度。
但是,如果您在整个过程中使用double
,编译器可以将d
保留在寄存器中 - 从而避免了进出内存的开销。
至于为什么它会让你用完寄存器...我不知道。程序的语义可能会导致具有相同值的双精度值和单精度值 - 在这种情况下,需要额外的寄存器。