Преобразуйте процедуру сравнения в Intel SIMD - PullRequest
0 голосов
/ 09 мая 2018

У меня есть процедура, где следует проверить, является ли число с плавающей запятой меньше нуля или нет.Если да, я должен сохранить знак и получить абсолютные значения.

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

Я изучил встроенные функции Intel SIMD и нашел эту инструкцию dst = _mm_cmplt_ps(a,b), которая генерирует вектор, содержащий (0xffffffff для true) или (0 за ложь) но я застрял там;Как я могу узнать, какой элемент вектора dst является отрицательным или нет, чтобы построить sign_vector.

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

С одним небольшим исключением (x == + 0.0f) вы можете сгенерировать целочисленную маску, используя инструкцию sign:

_mm_sign_epi32(_mm_set1_epi32(1), x)

Это отрицает 1, если x <0, но выдает знак == 0, когда x == 0. </p>

Если 0 не разрешено, x можно сделать ненулевым, указав 0<mask<0x80000000.

auto s=_mm_set1_epi32(1);
auto y=_mm_or_si128(x, s); // fix for x==0
s=_mm_sign_epi32(s, y);
0 голосов
/ 09 мая 2018

Предполагая, что ваши входные значения находятся в векторе __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 для знака, подумайте, можно ли просто работать с битами знака напрямую, и пропустите этот шаг.

...