5

我有很多调用的代码

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  

我发现的相关问题:

ARM (iPhone 3GS/4) 上的快速浮点到整数转换和浮点精度

在x86上将float转换为int的最快方法是什么

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

4

3 回答 3

6

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

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

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

要从 IDE 更改编译器设置,请使用 Project > Properties > Configuration Properties > C/C++ > Code Generation > Enable Enhanced Instruction Set。在命令行上是 /arch:SSE 或 /arch:SSE2。

于 2013-03-06T13:27:06.417 回答
1

因为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让您大开眼界,让编译器生成良好的矢量化代码有多难。

于 2013-03-06T13:43:03.837 回答
1

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

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

顺便提一句。在 Pentium 上,偶数FLD; FIST序列不应超过约 7 个时钟周期。

于 2013-03-06T13:50:13.127 回答