在阅读了主题之后,来自众多来源的绝大多数证据表明,在英特尔上使用标准C或C ++转换从浮点转换为整数是非常慢的。为了满足ANSI / ISO规范,Intel CPU需要执行大量指令,包括切换FPU硬件舍入模式所需的指令。
各种文档中描述了许多变通方法,但最干净,最便携的似乎是添加到C99和C ++ 0x标准的lrint()调用。许多文档都说编译器应该在启用优化时内联扩展这些函数,从而导致代码比传统的强制转换或函数调用更快。
我甚至发现了对gcc功能跟踪包的引用,将这种内联扩展添加到gcc优化器中,但在我自己的性能测试中,我无法使其工作。我所有的尝试都表明lrint性能要比简单的C或C ++样式转换慢得多。检查编译器的程序集输出,并反汇编编译对象总是显示对外部lrint()或lrintf()函数的显式调用。
我一直在使用的gcc版本是4.4.3和4.6.1,我在32位和64位x86目标上尝试了许多标志组合,包括明确启用SSE的选项。
如何让gcc内联展开lrint,并给我快速转换?
答案 0 :(得分:10)
lrint()
函数可能会引发域和范围错误。 libc处理此类错误的一种可能方法是设置errno
(参见C99 / C11第7.12.1节)。错误检查的开销可能非常大,在这种特殊情况下,似乎足以让优化器决定不进行内联。
gcc标志-fno-math-errno
(-ffast-math
的一部分)将禁用这些检查。如果你不依赖于符合标准的浮点语义处理,尤其是NaN和无穷大,那么调查-ffast-math
可能是个好主意......
答案 1 :(得分:0)
您是否尝试过将-finline-functions
标记为gcc。
您还可以指示GCC尝试使用选项-finline-functions.
请参阅http://gcc.gnu.org/onlinedocs/gcc/Inline.html
在这里你可以说gcc使所有函数都内联,但不会全部内联。 编译器使用一些启发式方法来确定函数是否足够小以便内联。还有一件事是递归函数也不会在这里内联。