加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

assembly – 将uint32的向量转换为float向量的最有效方法?

发布时间:2020-12-14 01:55:38 所属栏目:Windows 来源:网络整理
导读:x86没有从无符号int32转换为浮点的SSE指令.实现这一目标的最有效指令序列是什么? 编辑: 为了澄清,我想做以下标量操作的向量序列: unsigned int x = ...float res = (float)x; EDIT2:这是一个用于进行标量转换的简单算法. unsigned int x = ...float bias
x86没有从无符号int32转换为浮点的SSE指令.实现这一目标的最有效指令序列是什么?

编辑:
为了澄清,我想做以下标量操作的向量序列:

unsigned int x = ...
float res = (float)x;

EDIT2:这是一个用于进行标量转换的简单算法.

unsigned int x = ...
float bias = 0.f;
if (x > 0x7fffffff) {
    bias = (float)0x80000000;
    x -= 0x80000000;
}
res = signed_convert(x) + bias;

解决方法

您的天真标量算法无法提供正确的舍入转换 – 它会在某些输入上遭受双舍入.举个例子:如果x是0x88000081,那么转换为float的正确舍入结果是2281701632.0f,但是你的标量算法将返回2281701376.0f.

在我的头顶,你可以做如下正确的转换(正如我所说,这是我的头顶,所以它可能在某处保存指令):

movdqa   xmm1,xmm0    // make a copy of x
psrld    xmm0,16      // high 16 bits of x
pand     xmm1,[mask]   // low 16 bits of x
orps     xmm0,[onep39] // float(2^39 + high 16 bits of x)
cvtdq2ps xmm1,xmm1     // float(low 16 bits of x)
subps    xmm0,[onep39] // float(high 16 bits of x)
addps    xmm0,xmm1    // float(x)

常量具有以下值:

mask:   0000ffff 0000ffff 0000ffff 0000ffff
onep39: 53000000 53000000 53000000 53000000

这样做是将每个通道的高半部分和低半部分分别转换为浮点数,然后将这些转换后的值相加.因为每一半只有16位宽,所以转换为float不会产生任何舍入.仅在添加两半时才进行舍入;因为加法是一个正确舍入的操作,所以整个转换都是正确舍入的.

相比之下,你的天真实现首先将低31位转换为浮点数,这会导致舍入,然后有条件地将2 ^ 31加到该结果,这可能会导致第二次舍入.每当你在转换中有两个单独的舍入点时,除非你非常小心它们是如何发生的,否则你不应该期望结果被正确舍入.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读