2014-12-01 2 views
2

Я пытаюсь битрейт целых чисел вправо, используя встроенные функции. Код ниже пытается это сделать, но вывод выглядит не так, как ожидалось, возможно, я неправильно загружаю цифры или использую неправильную внутреннюю функцию. Вот результат:SSE внутреннее битовое смещение вправо

2 4 8 16 32 64 128 1 2 4 8 16 32 64 128 0 
512 1024 2048 4096 8192 16384 32768 0 
0 8192 0 16384 
8 0 16 0 

я стараюсь смотреть на эту thread, но это даже не попробовать использовать bitshift instructions with SSE intrinsics.

Вот полный код (скомпилируйте флаг SSE2).

#include <emmintrin.h> 
#include <stdio.h> 
#include <stdint.h> 

void print_16_num(__m128i var) 
{ 
    uint8_t *val = (uint8_t*) &var; 
    printf(" %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i \n", 
      val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7],val[8], val[9], val[10], val[11], val[12], val[13], val[14], val[15]); 
} 
void print_8_num(__m128i var) 
{ 
    uint16_t *val = (uint16_t*) &var; 
    printf(" %i %i %i %i %i %i %i %i \n", 
      val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]); 
} 
void print_4_num(__m128i var) 
{ 
    uint16_t *val = (uint16_t*) &var; 
    printf(" %i %i %i %i \n", 
      val[0], val[1], val[2], val[3]); 
} 
int main() 
{ 
    __m128i _16 = _mm_set_epi8(128, 64, 32, 16, 8, 4, 2, 1, 128, 64, 32, 16, 8, 4, 2, 1); 
    print_16_num(_mm_srli_si128(_16,1)); 

    __m128i _8 = _mm_set_epi16(128, 64, 32, 16, 8, 4, 2, 1); 
    print_8_num(_mm_srli_si128(_8,1)); 

    __m128i _4 = _mm_set_epi32(128, 64, 32, 16); 
    print_4_num(_mm_srli_si128(_4,1)); 

    _4 = _mm_set_epi32(128, 64, 32, 16); 
    print_4_num(_mm_srli_epi32(_4,1)); 

    return 0; 
} 
+0

Согласно документации, вы ссылочная '_mm_srli_si128' [сдвиги на байтах, а не бит] (HTTP: // математика .nju.edu.cn/помощь/mathhpc/док/Intel/куб.см/mergedProjects/intref_cls/общие/intref_sse2_int_shift.htm # slli_si128). –

+0

@RaymondChen О, неудивительно, что это не сработает. Итак, я предполагаю, что ссылка (на другой вопрос stackoverflow) - единственный способ сдвигаться по битам? – pandoragami

+0

afaik только сдвигает 128-битное смещение значения по байтам, 64,32,16 битов использования. Я предполагаю, что дизайнеры поставили под сомнение, в каком бизнесе вы бы переместили такое большое значение. – mukunda

ответ

4

Когда вы используете функции _mm_set_epi *, они сначала принимают свои параметры в качестве наиболее значимого элемента.

Например, первое утверждение,

__m128i _16 = _mm_set_epi8(128, 64, 32, 16, 8, 4, 2, 1, 128, 64, 32, 16, 8, 4, 2, 1);

загрузит переменную с этим значением:

0x80402010080402018040201008040201 
(128,64,32 ...) 

Затем вы переносите, что 128-битное значение, право 1 байт с _mm_srli_si128(_16,1) и вы получаете

0x00804020100804020180402010080402 

Когда вы читаете индивидуальные байтовые значения, байт [0] является наименее значимым байтом, который был бы самым дальним справа. (Так он печатает 02 04 08 и т.д. ...)

То же самое касается и других заявлений, хотя я думаю, что вы хотите, чтобы бросить в uint32_t* внутри функции print_4_num, а не uint16_t*.

Для последнего, _mm_srli_epi32(_4,1) сместит значение

0x00000080000000400000002000000010 
     (128) (64) (32) (16) 

право один раз немного, и он станет

0x00000040000000200000001000000008 

Но он будет печатать "8 0 16 0", потому что вы читаете 16 битовые значения, а не 32-битные значения в функции print_4_num:

0x0000 0040 0000 0020 0000 0010 0000 0008 
    (not used)  [3] [2] [1] [0] 

Fo г простой справочник, чтобы увидеть, какие функции делать то, что, проверить Intel Intrinsics Guide:

https://software.intel.com/sites/landingpage/IntrinsicsGuide/

+0

Мне просто пришлось переделать «print_4_num» и отлично работает для этого, мне все равно нужно было 32 бита. Благодарю. – pandoragami

 Смежные вопросы

  • Нет связанных вопросов^_^