Какой из них быстрее? - PullRequest
       90

Какой из них быстрее?

1 голос
/ 22 июня 2011

Я использую SSE2 в gcc 4.4.3. В моей программе мне нужно использовать, по меньшей мере, (0 - 7) 8-битный из 128-битного регистра SIMD. Пожалуйста, предложите способ, которым я могу быстро получить 8 бит.

Я пробовал с _mm_movepi64_pi64 или _mm_extract_epi16, оба из которых дают аналогичную производительность в моей программе. Я тоже пытался с профсоюзным подходом. union{__m128i a1, int a2[4]}. Хотя в тестовом примере это дало хорошие результаты, в моей программе этот подход был не очень хорошим.

Есть идеи ... (какой из вышеперечисленных трех способов мне следует использовать?)

1 Ответ

1 голос
/ 02 августа 2015

_mm_movepi64_pi64 перемещается из регистров XMM в MMX. Невозможно сделать правильный выбор, если только вы не хотите добавить больше SIMD в регистры MMX, а в вашем коде не хватает регистров XMM.

Если вы хотите, чтобы биты были индексом массива или чем-то еще, они должны быть в регистре GP, в этом случае вы хотите SSE4.1 _mm_extract_epi8.

Если вам нужно придерживаться SSE2, это самый быстрый способ получить байт 5 из xmm0:

pextrw eax, xmm0, 2
movzx eax, ah

Итак, мы надеемся, что компилятор будет работать так:

(uint8_t)(_mm_extract_epi16(var, n/2) >> ((n%2) * 8))

Менее эффективным будет сдвиг на байты _mm_bsrli_si128 (psrldq) для помещения нужного байта в младший байт регистра xmm, тогда movd (_mm_extract_epi16(var, 0) испускает movd, а не pextrw r32, xmm, 0, к счастью). Таким образом, вам не нужно делать ничего лишнего, если желаемый байт является нечетным байтом, который pextw оставил бы в старшей 8 результата. Все еще нет простого способа использовать это с индексом, который не является константой времени компиляции.

Хранение 16B в памяти и загрузка нужного вам элемента должны быть достаточно хорошими. (Что вы, вероятно, получите с помощью объединения, если компилятор не оптимизирует его до pextract инструкции). Компилятор будет использовать расположение в стеке размером 16B. Таким образом, store-> load forwarding должен работать нормально в этом случае, поэтому задержка будет низкой. Если вам нужно два отдельных элемента в две отдельные целочисленные переменные, это, вероятно, лучший выбор, возможно, победив несколько pextrw

...