5

我知道在浮点数和整数之间进行转换时可能会出现错误,但是性能如何(请忽略准确性问题)?

一般来说,如果我对不同算术类型的操作数(即不同的浮点类型(例如floatand double)和浮点/整数类型组合(例如floatand int))进行 n 元运算,性能会受到影响吗?是否存在经验法则,例如保持所有操作数的类型相同?

PS:我问是因为我正在编写一个表达式模板库,并且想知道是否允许对包含不同算术类型值的向量进行二进制运算。

4

3 回答 3

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 指出这一点。

于 2012-10-16T18:44:32.730 回答
2

在大多数机器上,浮点和整数格式之间的转换相当快,这得益于浮点硬件的特性。

但是,如果仅出于文档目的,当然应该努力以“正确”格式表达文字。并且在文档中使用显式强制转换也没有什么坏处。

于 2012-10-16T18:36:09.573 回答
2

通常会有一些性能损失,尽管与其他事物相比可以忽略不计。这是由于整数和浮点寄存器之间的数据迁移以及其他可能的 ABI 问题。

这些问题的答案总是相同的。怀疑?对其进行基准测试。性能在理论上很难预测。

于 2012-10-16T18:38:27.123 回答