Особенности SSE2: прямой доступ к памяти - PullRequest
2 голосов
/ 29 июля 2010

Многие инструкции SSE позволяют исходному операнду быть 16-байтовым выровненным адресом памяти. Например, различные (не) инструкции по упаковке. PUNCKLBW имеет следующую подпись:

PUNPCKLBW xmm1, xmm2 / m128

Теперь это кажется невозможным с помощью встроенных функций. Похоже, что для чтения чего-либо в памяти обязательно использовать встроенные функции _mm_load *. Это свойственно PUNPCKLBW:

__m128i _mm_unpacklo_epi8 (__m128i a, __m128i b);

(Насколько я знаю, тип __m128i всегда относится к регистру XMM.)

Теперь, почему это? Это довольно печально, так как я вижу некоторый потенциал оптимизации, обращаясь непосредственно к памяти ...

Ответы [ 2 ]

6 голосов
/ 29 июля 2010

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

TLDR: записать загрузку иоперация в intrinsics, и пусть компилятор ее оптимизирует.

Edit: тривиальный пример:

#include <emmintrin.h>
__m128i foo(__m128i *addr) {
    __m128i a = _mm_load_si128(addr);
    __m128i b = _mm_load_si128(addr + 1);
    return _mm_unpacklo_epi8(a, b);
}

Компиляция с gcc -Os -fomit-frame-pointer дает:

_foo:
movdqa      (%rdi), %xmm0
punpcklbw 16(%rdi), %xmm0
retq

Видите?Оптимизатор разберутся.

3 голосов
/ 01 августа 2010

Вы можете просто использовать ваши значения памяти напрямую. Например:

__m128i *p=static_cast<__m128i *>(_aligned_malloc(8*4,16));

for(int i=0;i<32;++i)
    reinterpret_cast<unsigned char *>(p)[i]=static_cast<unsigned char>(i);

__m128i xyz=_mm_unpackhi_epi8(p[0],p[1]);

Интересная часть результата:

; __m128i xyz=_mm_unpackhi_epi8(p[0],p[1]);
0040BC1B 66 0F 6F 00      movdqa      xmm0,xmmword ptr [eax] 
0040BC1F 66 0F 6F 48 10   movdqa      xmm1,xmmword ptr [eax+10h] 
0040BC24 66 0F 68 C1      punpckhbw   xmm0,xmm1 
0040BC28 66 0F 7F 04 24   movdqa      xmmword ptr [esp],xmm0 

Таким образом, компилятор делает плохую работу - или, возможно, этот путь быстрее и / или игра с опциями исправит это - но он генерирует работающий код, а код C ++ заявляет, что он хочет довольно прямо.

...