我有一个函数可以将浮点数组转换为无符号字符数组。这使用asm代码来实现。该代码是多年前编写的。现在我正在尝试用x64位构建解决方案。我知道X64不支持_asm。
删除asm依赖关系的最佳方法是什么?
如果我写C代码,最新的MS VC编译器会优化吗?有人知道实现这一点的助推或内在功能中是否有什么吗?
谢谢--Hari
我通过以下代码解决了问题,这比asm-更快
inline static void floatTOuchar(float * pInbuf, unsigned char * pOutbuf, long len)
{
std::copy(pInbuf, pInbuf + len, pOutbuf);
return ;
}
使用SSE2,可以使用内部函数从float
压缩到unsigned char
,饱和到无符号范围为0..255。
将浮点的四个向量转换为int的向量,使用CVTPS2DQ
(_mm_cvtps_epi32
)四舍五入到最近值,或者如果您想要默认的C floor
行为,则使用截断(_mm_cvttps_epi32
)进行转换。
然后将这些向量打包在一起,首先打包到具有两个PACKSSDW
(_mm_packs_epi32
)的有符号16位int的两个向量,然后打包到具有PACKUSWB
(_mm_packus_epi16
)的无符号8位int的一个向量。请注意,PACKUSWB采用带符号的输入,因此使用SSE4.1 PACKUSDW
作为第一步只会使事情变得更加困难(额外的屏蔽步骤)。int16_t
可以表示uint8_t
的所有可能值,所以没有问题。
存储uint8_t
的结果向量,并对接下来的四个浮点向量重复此操作。
在没有手动矢量化的情况下,正常的编译器输出对类似代码来说是很好的。
int ftoi_truncate(float f) { return f; }
cvttss2si eax, xmm0
ret
int dtoi(double d) { return nearbyint(d); }
cvtsd2si eax, xmm0 # only with -ffast-math, though. Without, you get a function call :(
ret
您可以尝试以下操作并告诉我:
inline int float2int( double d )
{
union Cast
{
double d;
long l;
};
volatile Cast c;
c.d = d + 6755399441055744.0;
return c.l;
}
// Same thing but it's not always optimizer safe
inline int float2int( double d )
{
d += 6755399441055744.0;
return reinterpret_cast<int&>(d);
}
for(int i = 0; i < HUGE_NUMBER; i++)
int_array[i] = float2int(float_array[i]);
所以技巧是双重参数。在当前代码中,函数将浮点值四舍五入到最接近的整数。如果需要截断,请使用6755399441055743.5(少0.5)。
内容丰富的文章,可在以下网址获得:http://stereopsis.com/sree/fpu2006.html