我通过执行以下循环来对一些基本例程进行基准测试:
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版本。即使通过引入一些依赖性来阻止矢量化循环的能力,回合速度也要慢10倍。对于地板等,生成的代码使用vroundss,对于圆形,有意大利面条代码...有什么想法吗?
编辑:我正在使用-ffast-math,-mfpmath = sse,-fno-math-errno,-O3,-std = c ++ 17,-march = core-avx2 -mavx2 -mfma
答案 0 :(得分:3)
问题在于,没有任何SSE舍入模式为round
指定正确的舍入:
这些函数将x舍入到最接近的整数,但是将中途情况舍入为零 (无论当前的取整方向如何,请参见fenv(3)),而不是取整 甚至像rint(3)这样的整数。
如果您想要更快的代码,可以尝试测试rint
而不是round
,因为这指定了SSE确实支持的舍入模式。
答案 1 :(得分:1)
要注意的一件事是,像floor(x + 0.5)
这样的表达式虽然不具有与round(x)
相同的语义,但在几乎所有用例中都是有效的替代品,我怀疑它是否接近比floor(x)
慢10倍。