gpt4 book ai didi

assembly - 将 uint32 向量转换为浮点向量的最有效方法?

转载 作者:行者123 更新时间:2023-12-04 18:48:58 26 4
gpt4 key购买 nike

x86 没有从 转换的 SSE 指令未签名 int32 到浮点。实现这一目标的最有效指令序列是什么?

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

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;

最佳答案

您的天真的标量算法无法提供正确舍入的转换——它会在某些输入上遭受双重舍入。例如:如果 x0x88000081 ,则转换为 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

这样做是将每个 channel 的高半和低半分别转换为浮点数,然后将这些转换后的值加在一起。因为每一半只有 16 位宽,所以转换为浮点数不会导致任何舍入。只有当两半相加时才会发生舍入;因为加法是一个正确舍入的运算,所以整个转换都是正确舍入的。

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

关于assembly - 将 uint32 向量转换为浮点向量的最有效方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9151711/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com