Я оптимизирую некоторый код для микроархитектуры Intel x86 Nehalem с использованием встроенных функций SSE.
Часть моей программы вычисляет 4-точечные продукты и добавляет каждый результат к предыдущим значениям в непрерывном фрагменте массива,В частности,
tmp0 = _mm_dp_ps(A_0m, B_0m, 0xF1);
tmp1 = _mm_dp_ps(A_1m, B_0m, 0xF2);
tmp2 = _mm_dp_ps(A_2m, B_0m, 0xF4);
tmp3 = _mm_dp_ps(A_3m, B_0m, 0xF8);
tmp0 = _mm_add_ps(tmp0, tmp1);
tmp0 = _mm_add_ps(tmp0, tmp2);
tmp0 = _mm_add_ps(tmp0, tmp3);
tmp0 = _mm_add_ps(tmp0, C_0n);
_mm_storeu_ps(C_2, tmp0);
Обратите внимание, что я собираюсь сделать это, используя 4 временных регистра xmm для хранения результата каждого точечного произведения.В каждом регистре xmm результат помещается в уникальные 32 бита относительно других временных регистров xmm, так что конечный результат выглядит следующим образом:
tmp0 = R0-ноль-ноль-ноль
tmp1 = ноль-R1-ноль-ноль
tmp2 = ноль-ноль-R2-ноль
tmp3 = ноль-ноль-ноль-R3
Я объединяю значениясодержится в каждой переменной tmp в одну переменную xmm, суммируя их с помощью следующих инструкций:
tmp0 = _mm_add_ps(tmp0, tmp1);
tmp0 = _mm_add_ps(tmp0, tmp2);
tmp0 = _mm_add_ps(tmp0, tmp3);
Наконец, я добавляю регистр, содержащий все 4 результата точечных произведений, в непрерывную часть массива так, чтобыиндексы массива увеличиваются на точечное произведение, например: (C_0n - это 4 значения в массиве, который должен быть обновлен; C_2 - адрес, указывающий на эти 4 значения):
tmp0 = _mm_add_ps(tmp0, C_0n);
_mm_storeu_ps(C_2, tmp0);
Я хочуузнать, существует ли менее округлый, более эффективный способ получения результатов точечных произведений и добавления их в непрерывный фрагмент массива.Таким образом, я делаю 3 добавления между регистрами, в которых есть только 1 ненулевое значение.Кажется, должен быть более эффективный способ сделать это.
Я ценю любую помощь.Спасибо.