【问题标题】:_ftol2_sse, are there faster options?_ftol2_sse,有更快的选择吗?
【发布时间】:2013-03-06 12:57:19
【问题描述】:

我的代码调用了很多

int myNumber = (int)(floatNumber);

总共占用了我大约 10% 的 CPU 时间(根据分析器)。虽然我可以把它留在那里,但我想知道是否有更快的选择,所以我尝试四处搜索,偶然发现

http://devmaster.net/forums/topic/7804-fast-int-float-conversion-routines/ http://stereopsis.com/FPU.html

我尝试实现那里给出的 Real2Int() 函数,但它给了我错误的结果,并且运行速度较慢。现在我想知道,是否有更快的实现将双精度/浮点值设置为整数,或者 SSE2 版本是否尽可能快?我发现的页面有点早,所以它可能已经过时了,而新的 STL 在这方面更快。

当前的实现是:

013B1030  call        _ftol2_sse (13B19A0h)

013B19A0  cmp         dword ptr [___sse2_available (13B3378h)],0  
013B19A7  je          _ftol2 (13B19D6h)  
013B19A9  push        ebp  
013B19AA  mov         ebp,esp  
013B19AC  sub         esp,8  
013B19AF  and         esp,0FFFFFFF8h  
013B19B2  fstp        qword ptr [esp]  
013B19B5  cvttsd2si   eax,mmword ptr [esp]  
013B19BA  leave  
013B19BB  ret  

我发现的相关问题:

Fast float to int conversion and floating point precision on ARM (iPhone 3GS/4)

What is the fastest way to convert float to int on x86

由于两者都是旧的,或者是基于 ARM 的,我想知道是否有当前的方法可以做到这一点。请注意,它说最好的转换是不会发生的,但我需要它,所以这是不可能的。

【问题讨论】:

    标签: c++ floating-point


    【解决方案1】:

    如果您的目标是通用 x86 硬件,那将是难以超越的。运行时不确定目标机器是否有 SSE 单元。如果是这样,它可以做 x64 编译器所做的事情并内联 cvttss2si 操作码。但是由于运行时必须检查 SSE 单元是否可用,因此您只剩下当前的实现。这就是 ftol2_sse 的实现。更重要的是,它将值传递到 x87 寄存器中,然后如果 SSE 单元可用,则将其传输到 SSE 寄存器。

    您可以告诉 x86 编译器以具有 SSE 单元的机器为目标。然后编译器确实会发出一个简单的cvttss2si 内联操作码。这将尽可能快。但是,如果您在旧机器上运行代码,那么它将失败。也许您可以提供两种版本,一种用于具有 SSE 的机器,一种用于没有 SSE 的机器。

    这不会让你获得那么多。它只是为了避免 ftol2_sse 的所有开销,这些开销发生在您实际到达完成工作的 cvttss2si 操作码之前。

    要从 IDE 更改编译器设置,请使用项目 > 属性 > 配置属性 > C/C++ > 代码生成 > 启用增强指令集。在命令行上是 /arch:SSE 或 /arch:SSE2。

    【讨论】:

      【解决方案2】:

      对于double,我不认为你能改进结果,但如果你有很多floats 需要转换,使用打包转换可能会有所帮助,以下是nasm 代码:

      global _start
      
      section .data
        align 16
        fv1:  dd 1.1, 2.5, 2.51, 3.6
      
      section .text
        _start:
      
        cvtps2dq  xmm1, [fv1] ; Convert four 32-bit(single precision) floats to 32-bit(double word) integers and place the result in xmm1 
      

      应该有内在函数代码可以让您以更简单的方式做同样的事情,但我不熟悉使用内在函数库。虽然您没有使用 gcc,但这篇文章 Auto-vectorization with gcc 4.7 让您大开眼界,让编译器生成良好的矢量化代码是多么困难。

      【讨论】:

        【解决方案3】:

        如果您需要速度和大量目标机器,您最好引入所有算法的快速 SSE 版本以及通用算法 - 并选择要在更高级别执行的算法。

        这也意味着 ABI 也针对 SSE 进行了优化;并且您可以在可用时对计算进行矢量化,并且控制逻辑也针对架构进行了优化。

        顺便说一句。在 Pentium 上,即使 FLD; FIST 序列也应该不超过 ~7 个时钟周期。

        【讨论】:

        • 您需要更改舍入模式以获得正确的截断。据我所知,更改 x87 状态字很慢。
        • @infact 的评论是准确的
        • 好点。那么不改变状态字经常是有意义的。
        猜你喜欢
        • 2020-12-08
        • 2014-11-02
        • 1970-01-01
        • 1970-01-01
        • 2015-10-26
        • 2021-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多