我知道在浮点数和整数之间进行转换时可能出现的错误,但性能如何(请忽略准确性问题)?
如果我对不同算术类型的操作数进行n元运算,即在不同的浮点类型(例如float
和double
)和浮点数/上,性能通常会受到影响整数类型组合(例如float
和int
)?是否存在经验法则,例如,保持所有操作数的类型相同?
P.S。:我在问,因为我正在编写一个表达式模板库,想知道是否允许对包含不同算术类型值的向量进行二进制运算。
答案 0 :(得分:5)
我怀疑这个问题的答案会因目标架构而异,因为转换可以(但可能不会)在硬件中发生。例如,考虑以下代码,它会导致int和float之间的一些相互转换:
int main (int argc, char** argv)
{
int precoarced = 35;
// precoarced gets forced to float
float result = 0.5 + precoarced;
// and now we force it back to int
return (int)result;
// I wonder what the disassembly looks like in different environments?
}
当我尝试使用默认设置使用g ++(我使用的是Ubuntu,x86)编译它时,并使用gdb进行反汇编:
0x00000000004004b4 <+0>: push %rbp
0x00000000004004b5 <+1>: mov %rsp,%rbp
0x00000000004004b8 <+4>: mov %edi,-0x14(%rbp)
0x00000000004004bb <+7>: mov %rsi,-0x20(%rbp)
0x00000000004004bf <+11>: movl $0x23,-0x8(%rbp)
0x00000000004004c6 <+18>: cvtsi2sdl -0x8(%rbp),%xmm0
0x00000000004004cb <+23>: movsd 0x10d(%rip),%xmm1 # 0x4005e0
0x00000000004004d3 <+31>: addsd %xmm1,%xmm0
0x00000000004004d7 <+35>: unpcklpd %xmm0,%xmm0
0x00000000004004db <+39>: cvtpd2ps %xmm0,%xmm0
0x00000000004004df <+43>: movss %xmm0,-0x4(%rbp)
0x00000000004004e4 <+48>: movss -0x4(%rbp),%xmm0
0x00000000004004e9 <+53>: cvttss2si %xmm0,%eax
0x00000000004004ed <+57>: pop %rbp
0x00000000004004ee <+58>: retq
请注意带有cvt前缀助记符的说明。这些是转换说明。因此,在这种情况下,转换是在硬件中的一些指令中进行的。因此,根据这些指令的成本周期,可能会相当快。但同样,不同的架构(或不同的编译器)可能会改变故事。
编辑:有趣的是,由于我不小心指定0.5而不是0.5f,因此在那里有额外的转换。这就是为什么cvtpd2ps操作在那里。
编辑:x86已经有很长时间的FP支持(从80年代开始),因此针对x86的C ++编译器通常会使用硬件(除非编译器严重落后于时代)。感谢Hot Licks指出这一点。
答案 1 :(得分:2)
在大多数机器上,浮点和int格式之间的转换相当快,受浮点硬件功能的辅助。
但是,当然,如果仅出于文档目的,应该努力以“正确”格式表达文字。对于文档来说,使用显式强制转换也没有什么坏处。
答案 2 :(得分:2)
通常会有一些性能损失,但与其他事情相比可以忽略不计。这是由于积分寄存器和浮点寄存器之间的数据迁移以及其他可能的ABI问题。
这些问题的答案总是一样的。怀疑? 基准测试。性能在理论上几乎无法预测。