舍入比LLVM中的floor/ceil/int慢得多

round much slower than floor/ceil/int in LLVM

本文关键字:int ceil 舍入 LLVM 中的 floor      更新时间:2023-10-16

我通过执行循环来对一些基本例程进行基准测试,例如:

float *src, *dst;
for (int i=0; i<cnt; i++) dst[i] = round(src[i]);

全部与AVX2目标,最新的CLANG。有趣的是,floor(x), ceil(x), int(x)...一切似乎都很快。但是 round(x) 似乎非常慢,并且正在反汇编有一些奇怪的意大利面条代码,而不是较新的 SSE 或 AVX 版本。即使通过引入一些依赖关系来阻止矢量化循环的能力,round 也会慢 10 倍。对于地板等,生成的代码使用 vroundss,对于圆形,有意大利面条代码......有什么想法吗?

编辑:我正在使用-ffast-math,-mfpmath=sse,-fno-math-errno,-O3,-std=c ++ 17,-march=core-avx2 -mavx2 -mfma

问题是没有一个 SSE 舍入模式指定正确的舍入round

这些函数将 x 舍入到最接近的整数,但从零四舍五入到离零的中间情况 (无论当前的舍入方向如何,请参阅 fenv(3)),而不是最接近的方向 偶数像 rint(3) 这样的整数。

如果你想要更快的代码,你可以尝试测试rint而不是round,因为它指定了SSE支持的舍入模式。

需要注意的一件事是,像 floor(x + 0.5) 这样的表达式虽然没有与round(x)完全相同的语义,但在几乎所有用例中都是有效的替代品,我怀疑它比 floor(x) 慢 10 倍。