Я пытаюсь оптимизировать следующее sum{vec4[indexarray[i]] * scalar[i]}
, где vec4
- это float[4]
, а scalar
- это число с плавающей точкой. С 128-битными регистрами это сводится к
sum = _mm_fmadd_ps(
_mm_loadu_ps(vec4[indexarray[i]]),
_mm_set_ps1(scalar[i]),
sum);
Если я хочу выполнить FMA на 256-битных регистрах, мне придется сделать что-то вроде
__m256 coef = _mm256_set_m128(
_mm_set_ps1(scalar[2 * i + 0]),
_mm_set_ps1(scalar[2 * i + 1]));
__m256 vec = _mm256_set_m128(
_mm_loadu_ps(vec4[indexarray[2 * i + 0]]),
_mm_loadu_ps(vec4[indexarray[2 * i + 1]]));
sum = _mm256_fmadd_ps(vec, coef, sum);
вместе с перемешиванием и добавлением в конце для суммирования верхней и нижней полос.
Теоретически, я получаю 5 в задержке (при условии архитектуры Haswell) от единственного FMA, но теряю 2x3 в задержке от _mm256_set_m128
.
Есть ли способ сделать это быстрее, используя регистры ymm, или все выгоды от одного FMA будут с интересом компенсированы объединением регистров xmm?