Понимание оптимизации умножения матриц SSE3

В отношении http://blogs.msdn.com/b/xiangfan/archive/2009/04/28/optimize-your-code-matrix-multiplication.aspx.

template<>
void SeqMatrixMult4(int size, float** m1, float** m2, float** result)
{
Transpose(size, m2);
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
__m128 c = _mm_setzero_ps();

for (int k = 0; k < size; k += 4) {
c = _mm_add_ps(c, _mm_mul_ps(_mm_load_ps(&m1[i][k]), _mm_load_ps(&m2[j][k])));
}
c = _mm_hadd_ps(c, c);
c = _mm_hadd_ps(c, c);
_mm_store_ss(&result[i][j], c);
}
}
Transpose(size, m2);
}

Почему там еще 2 _mm_hadd_ps(c, c) после внутреннего самого цикла? Чтобы проверить мое понимание: этот код загружает 4 числа с плавающей запятой от m1 и еще 4 числа с м2, а затем умножает их, в результате чего получается 4 числа с плавающей запятой (__m128). Затем я суммирую их в c (на данный момент его все еще 4 поплавка?). Затем после цикла я hadd этот результат дважды? Что это делает?


Мой код, слегка переписанный, выдает неправильный результат

long long start, end;
__m128 v1, v2, vMul, vRes;
vRes = _mm_setzero_ps();

start = wall_clock_time();
transpose_matrix(m2);
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
float tmp = 0;
for (int k = 0; k < SIZE; k+=4) {
v1 = _mm_load_ps(&m1[i][k]);
v2 = _mm_load_ps(&m2[j][k]);
vMul = _mm_mul_ps(v1, v2);

vRes = _mm_add_ps(vRes, vMul);
}
vRes = _mm_hadd_ps(vRes, vRes);
_mm_store_ss(&result[i][j], vRes);
}
}
end = wall_clock_time();
fprintf(stderr, "Optimized Matrix multiplication took %1.2f seconds\n", ((float)(end - start))/1000000000);

// reverse the transposition
transpose_matrix(m2);

0

Решение

haddps не суммирует все четыре элемента в векторе. Два haddps инструкции необходимы для получения полной горизонтальной суммы.

Если мы нумеруем элементы вектора {c0,c1,c2,c3}, первый haddps производит {c0+c1, c2+c3, c0+c1, c2+c3}, Второй производит {c0+c1+c2+c3, <same thing in the other lanes>},

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]