有没有办法使用AVX / SSE来获取浮点数向量,向下舍入并生成一个整数向量?所有楼层内在方法似乎都产生浮点的最终向量,这是奇怪的,因为舍入产生一个整数!
答案 0 :(得分:4)
SSE已经从FP转换为整数,您可以选择截断(朝向零)或当前的舍入模式(通常是IEEE默认模式,最接近并列最小值,可以舍入为偶数。与nearbyint()
类似,与{{1}不同其中,tiebreak远离0。如果你需要x86上的舍入模式,you have to emulate it, perhaps with truncate as a building block。)
相关说明为CVTPS2DQ和CVTTPS2DQ,用于将打包的单精度round()
转换为签名的双字整数。助记符中带有额外T的版本执行Truncation而不是当前的舍入模式。
float
或者使用内在函数; xmm0 is assumed to be packed float input vector
cvttps2dq xmm0, xmm0
; xmm0 now contains the (rounded) packed integer vector
对于其他两种舍入模式,x86提供硬件,floor(朝向-Inf)和ceil(朝向+ Inf),一种简单的方法是在转换为整数之前使用此SSE4.1 / AVX ROUNDPS指令
代码如下所示:
__m128i _mm_cvt[t]ps_epi32(__m128 a)
对于AVX ymm向量,使用' V'并将xmm更改为ymm&#39。
ROUNDPS就像这样工作
以xmm2 / m128为单位的圆形打包单精度浮点值,并将结果放在xmm1中。舍入模式由imm8确定。
舍入模式(立即/第三个操作数)可以具有以下值(取自当前英特尔文档的表roundps xmm0, xmm0, 1 ; nearest=0, floor=1, ceil=2, trunc=3
cvtps2dq xmm0, xmm0 ; or cvttps2dq, doesn't matter
; xmm0 now contains the floored packed integer vector
):
4-15 - Rounding Modes and Encoding of Rounding Control (RC) Field
舍入操作的返回向量为Rounding Mode RC Field Setting Description
----------------------------------------------------------
Round to nearest (even) 00B Rounded result is the closest to the infinitely precise result. If two values are equally close, the result is nearest (even) the even value (i.e., the integer value with the least-significant bit of zero).
Round down (toward −∞) 01B Rounded result is closest to but no greater than the infinitely precise result.
Round up (toward +∞) 10B Rounded result is closest to but no less than the infinitely precise result.
Round toward 0 (truncate) 11B Rounded result is closest to but no greater in absolute value than the infinitely precise result.
而非float
的可能原因可能是,通过这种方式,进一步的操作可能始终是浮点运算(在舍入值上)和转换为如图所示,int
将是微不足道的。
相应的内在函数可在参考文档中找到。将上述代码转换为内在函数(取决于int
)的示例是:
Rounding Control (RC) Field
答案 1 :(得分:1)
使用转换说明:
int _mm_cvt_ss2si (__m128 a)
将a
的低32位浮点组件转换为整数并返回该整数。 a
的上三个组成部分将被忽略。
__m128i _mm_cvtps_epi32 (__m128 a);
将所有四个32位浮点数转换为整数,并返回4个32位整数的向量。
这些是经常使用的。有additional variations来处理转化。
答案 2 :(得分:1)
单指令选项:
__m128i _mm_cvttps_epi32(__m128 a)
__m128i _mm_cvtps_epi32(__m128 a)
两条指令,使用SSE4.1 ROUNDPS
然后使用cvtps_epi32
-INF
:__m128 _mm_floor_ps(__m128 s1)
+INF
:__m128 _mm_ceil_ps(__m128 s1)
如果您想以FP格式保存数据,请仅使用其他截断或最近的roundps
形式。
对于正数,截断和地板是相同的。对于负整数,cvtt(-4.9) = -4
,但floor(-4.9) = -5.0
。请参阅floorf()
与truncf()
。
如果FP值超出INT_MIN
到INT_MAX
范围,cvttps
and cvtps
will give you 0x80000000
(即INT_MIN
,只有符号位设置),英特尔称之为&#34 ;整数无限期"值。它还会引发FP无效异常,但默认情况下会屏蔽FP异常。