AVX/SSE 将浮点符号掩码转换为 __m128i

Posted

技术标签:

【中文标题】AVX/SSE 将浮点符号掩码转换为 __m128i【英文标题】:AVX/SSE convert floating point sign mask to __m128i 【发布时间】:2018-04-26 12:13:09 【问题描述】:

我正在使用以下内容来提取__mm128 的符号位:

const int sign_mask = _mm_movemask_ps(a);

我现在想使用以下方法来混合两个向量:

v_add = _mm_blendv_ps(a, v_add_neg, _mm_castsi128_ps(v_mask));

v_mask 需要来自 sign_mask,但我找不到这样做的内在函数。

代码的目的是根据另一个向量对应元素中的符号来改变a向量元素的符号。

【问题讨论】:

您可以将所有可能的 v_mask 存储在一个数组中,由 sign_mask 索引。但我不明白你为什么要通过sign_mask,你应该坚持使用向量。 我后来发现使用向量 AND 和 OR 来做到这一点更容易。没有将符号提取到向量中的内在函数(据我所知)。 我不确定你是否需要这样的内在函数,因为_mm_blendv_ps (a, b,c) 使用c 的符号位在ab 的元素之间进行选择。可能这只是你想要的? 【参考方案1】:

您可以使用_mm_blendv_ps(a, v_add_neg, a)blendvps 接受 vector 输入,并使用每个元素的符号位作为该元素的混合条件。

如果你需要它作为一个整数,你只需要movemask,不是一个向量,例如将其用作查找表的索引,或者在所有具有某些属性的向量元素上进行分支。

代码的目的是根据另一个向量对应元素中的符号来更改向量元素的符号。

使用布尔值来操作符号位

 // pick your favourite way to express a 0x80000000 FP constant: just the sign bit set.
__m128  sign_v = _mm_and_ps(v, _mm_set1_ps(-0.0));
__m128  a_times_sign_v = _mm_xor_ps(a, sign_v);

翻转 a 中元素的符号,其中 v 已设置符号位。

请注意,它将-0.0 视为负数,而不是零,并且-NaN 也被视为正常负数。如果您不希望这样,请使用 _mm_cmplt_ps 和左移或 AND 比较掩码以获得 xorps 的符号位掩码。

【讨论】:

评论不用于扩展讨论;这个对话是moved to chat。 出于好奇,您在 pd 上的 Log 和 Exp 使用什么库? @IamIC:上次我需要它时,我使用的是 GPLed 的 Agner Fog 的矢量类库 (agner.org/optimize)。但是我需要一个快速逼近 Log() 来打包 float,所以我做了一些研究并制作了一个非常快速的版本,它对于我的目的来说足够准确(作为 asinh 的一部分)。请参阅Efficient implementation of log2(__m256d) in AVX2 了解我使用的概述(JRF 的 6 阶多项式,使用 AVX2 FMA)。我不需要打包的-double 或接近 1 或 0.5 ulp 精度的准确日志。 谢谢你,彼得。你一如既往地乐于助人。

以上是关于AVX/SSE 将浮点符号掩码转换为 __m128i的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SSE 将 _m128i 转换为无符号整数?

如何将两个_pd 转换为一个_ps?

将浮点向量转换为 16 位 int 而不饱和

尝试在 SSE 编程中使用和掩码添加 __m128

如何获得英特尔架构 SIMD __m128 的标志

有没有办法根据编译时未知的掩码长度来掩码 __m128i 寄存器的一端?