Я уже три раза пытался использовать массивы векторов SIMD для замены групп загрузок и хранилищ SIMD. Это заманчиво, но кажется неудачной ставкой, потому что это никогда не ускоряет работу и, во всяком случае, приводит к замедлению кода. Это первый раз, когда я пытался просмотреть ассемблер для проекта, где код массива определенно медленнее, чем код загрузки/сохранения, и я был удивлен, увидев 13 инструкций для кода массива по сравнению с 8 инструкциями для кода загрузки/сохранения, чтобы получить тот же результат.
Мои вопросы:
- Является ли 13-строчный ассемблер ниже значительно медленнее, чем 8-строчный блок?
- Являются ли массивы simd-векторов естественно неэффективными по сравнению с эквивалентным кодом, использующим загрузки/сохранения с массивами фундаментальных типов данных? Или, может быть, это просто компилятор MSVC плохо справляется со своей задачей? Или, может быть, ответ на проблемы с кешем для массивов разного размера разный? Мои сим-массивы обычно довольно малы, обычно около 200 двойников.
//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
Мобильная версия