Являются ли массивы simd-векторов естественно неэффективными?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Являются ли массивы simd-векторов естественно неэффективными?

Сообщение Anonymous »

Я компилирую код C++ с помощью MSVC. Мой пример кода ниже — SSE2, потому что я использую диспетчер, а это означает, что Visual Studio не будет выгружать сборку для AVX или AVX512. Мой вариант использования — AVX2 и AVX512.
Я уже три раза пытался использовать массивы векторов SIMD для замены групп загрузок и хранилищ SIMD. Это заманчиво, но кажется неудачной ставкой, потому что это никогда не ускоряет работу и, во всяком случае, приводит к замедлению кода. Это первый раз, когда я пытался просмотреть ассемблер для проекта, где код массива определенно медленнее, чем код загрузки/сохранения, и я был удивлен, увидев 13 инструкций для кода массива по сравнению с 8 инструкциями для кода загрузки/сохранения, чтобы получить тот же результат.
Мои вопросы:
  • Является ли 13-строчный ассемблер ниже значительно медленнее, чем 8-строчный блок?
  • Являются ли массивы simd-векторов естественно неэффективными по сравнению с эквивалентным кодом, использующим загрузки/сохранения с массивами фундаментальных типов данных? Или, может быть, это просто компилятор MSVC плохо справляется со своей задачей? Или, может быть, ответ на проблемы с кешем для массивов разного размера разный? Мои сим-массивы обычно довольно малы, обычно около 200 двойников.
//__m128d* TR_vec = new __m128d[vec_arraysize];
//double* TR = (double*)TR_vec;
//const __m128d vec_dcp = _mm_set1_pd(dc_p);
//const __m128d vec_dcq = _mm_set1_pd(dc_q);

for (jj = bsteps - 1; jj > -1; jj--)
{
jjN = ((jj + 1) + vectorsize - 1) & (-vectorsize);
for (kk = 0; kk < jjN; kk += vectorsize)
{
#ifdef ARRAY_OF_SIMDS
vndx = kk >> 1;
TR_vec[vndx] = _mm_add_pd(_mm_mul_pd(vec_dcp, _mm_load_pd(TR + (kk + 1))), _mm_mul_pd(vec_dcq, TR_vec[vndx]));
#else
_mm_store_pd(TR + kk, _mm_add_pd(_mm_mul_pd(vec_dcp, _mm_load_pd(TR + (kk + 1))), _mm_mul_pd(vec_dcq, _mm_load_pd(TR + kk))));
#endif
}
}

//; 29161:
TR_vec[vndx] = _mm_add_pd(_mm_mul_pd(vec_dcp, _mm_load_pd(TR + (kk + 1))), _mm_mul_pd(vec_dcq, TR_vec[vndx]));

movaps xmm1, xmm7
mov rax, rcx
movaps xmm0, xmm6
mulpd xmm0, XMMWORD PTR [r8]
add rax, rax
add rdx, 2
add r8, 16
mulpd xmm1, XMMWORD PTR [rdi+rax*8]
mov rax, rcx
add rax, rax
addpd xmm1, xmm0
movups XMMWORD PTR [rdi+rax*8], xmm1
cmp rdx, r9

//; 29168:
_mm_store_pd(TR + kk, _mm_add_pd(_mm_mul_pd(vec_dcp, _mm_load_pd(TR + (kk + 1))), _mm_mul_pd(vec_dcq, _mm_load_pd(TR + kk))));

movaps xmm1, xmm6
movaps xmm0, xmm7
mulpd xmm1, XMMWORD PTR [rdi+rax*8+8]
mulpd xmm0, XMMWORD PTR [rdi+rax*8]
addpd xmm1, xmm0
movups XMMWORD PTR [rdi+rax*8], xmm1
add rax, 2
cmp rax, rcx

//AVX2 dumped by Visual Studio:

TR_vec[vndx] = _mm256_add_pd(_mm256_mul_pd(vec_dcp, _mm256_load_pd(TR + (kk + 1))), _mm256_mul_pd(vec_dcq, TR_vec[vndx]));

mov rax, rcx
shl rax, 5
vmulpd ymm1, ymm5, YMMWORD PTR [rax+rdi]
movsxd rax, r8d
add r8d, 4
vmulpd ymm0, ymm4, YMMWORD PTR [rdi+rax*8]
mov rax, rcx
shl rax, 5
vaddpd ymm1, ymm0, ymm1
vmovupd YMMWORD PTR [rax+rdi], ymm1
cmp rdx, r9

_mm256_store_pd(TR + kk, _mm256_add_pd(_mm256_mul_pd(vec_dcp, _mm256_load_pd(TR + (kk + 1))), _mm256_mul_pd(vec_dcq, _mm256_load_pd(TR + kk))));

vmulpd ymm1, ymm5, YMMWORD PTR [rcx]
vmulpd ymm0, ymm4, YMMWORD PTR [rcx+8]
lea rcx, QWORD PTR [rcx+32]
vaddpd ymm1, ymm0, ymm1
vmovupd YMMWORD PTR [rcx-32], ymm1
sub rdx, 1


Подробнее здесь: https://stackoverflow.com/questions/797 ... nefficient
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»