C语言 将比较例程转换为英特尔 SIMD



我有一个例程,其中应该测试浮点数是否小于零。 如果是,我应该存储符号,我得到它是绝对值。

int sign = 1;
if (x < 0)
{
sign = -1;
}
x = fabs(x);

我研究了英特尔 SIMD 内联函数,发现这条指令dst = _mm_cmplt_ps(a,b)生成一个包含 (0xffffffff 表示真(或 (0 表示假( 的向量,但我被困在那里; 我怎么知道dst向量的哪个元素是负的或不构建sign_vector

除了一个小的例外(x==+0.0f(,您可以使用指令生成整数掩码sign

_mm_sign_epi32(_mm_set1_epi32(1), x)

如果 x<0,这将否定 1,但在 x==0 时产生符号==0。

如果不允许 0,则可以通过使用0<mask<0x80000000进行 oring 使 x 不为零。

auto s=_mm_set1_epi32(1);
auto y=_mm_or_si128(x, s); // fix for x==0
s=_mm_sign_epi32(s, y);

假设您的输入值位于向量__m128 v中:

__m128 vmask = _mm_set1_ps(-0.0f);      // create sign bit mask
__m128 vsign = _mm_and_ps(v, vmask);    // create vector of sign bits (MSB)
__m128i vsigni = _mm_add_epi32(_mm_srai_epi32((__m128i)vsign, 30), _mm_set1_epi32(1));
// convert sign bits to integer +1/-1 (if needed (*))
v = _mm_andnot_ps(vmask, v);            // clear sign bits in v (i.e. v = fabsf(v))

(*( 与其浪费为符号生成 +1/-1 的周期,不如考虑是否可以直接使用符号位,并省略此步骤。

最新更新