Я узнал, что некоторые процессоры Intel/AMD могут делать одновременное умножение и добавлять с помощью SSE/AVX:
FLOPS за цикл для песчаного моста и haswell SSE2/AVX/AVX2.
Мне нравится знать, как сделать это лучше всего в коде, и я также хочу знать, как это делается внутри CPU. Я имею в виду суперскалярную архитектуру. Скажем, я хочу сделать длинную сумму, такую как следующее в SSE:
//sum = a1*b1 + a2*b2 + a3*b3 +... where a is a scalar and b is a SIMD vector (e.g. from matrix multiplication)
sum = _mm_set1_ps(0.0f);
a1 = _mm_set1_ps(a[0]);
b1 = _mm_load_ps(&b[0]);
sum = _mm_add_ps(sum, _mm_mul_ps(a1, b1));
a2 = _mm_set1_ps(a[1]);
b2 = _mm_load_ps(&b[4]);
sum = _mm_add_ps(sum, _mm_mul_ps(a2, b2));
a3 = _mm_set1_ps(a[2]);
b3 = _mm_load_ps(&b[8]);
sum = _mm_add_ps(sum, _mm_mul_ps(a3, b3));
...
Мой вопрос в том, как это преобразуется в одновременное умножение и добавление? Могут ли данные быть зависимыми? Я имею в виду, может ли процессор делать _mm_add_ps(sum, _mm_mul_ps(a1, b1))
одновременно или делать регистры, используемые в умножении, и добавлять должны быть независимыми?
Наконец, как это относится к FMA (с Haswell)? Является ли _mm_add_ps(sum, _mm_mul_ps(a1, b1))
автоматически преобразовывается в одну инструкцию FMA или микрооперацию?