2015-11-21 2 views
1

Я пытаюсь преобразовать SSE-функцию в AVX. Функция делает вектор-матричного умножения, вот мой работает SSE код:Преобразование SSE-вектора кода умножения в AVX

void multiply_matrix_by_vector_SSE(float* m, float* v, float* result, unsigned const int vector_dims) 
{ 
    size_t i, j; 
    for (i = 0; i < vector_dims; ++i) 
    { 
     __m128 acc = _mm_setzero_ps(); 
     for (j = 0; j < vector_dims; j += 4) 
     { 
      __m128 vec = _mm_load_ps(&v[j]); 
      __m128 mat = _mm_load_ps(&m[j + vector_dims * i]); 
      //acc = _mm_add_ps(acc, _mm_mul_ps(mat, vec)); 
      acc = _mm_fmadd_ps(mat, vec, acc); 
     } 
     acc = _mm_hadd_ps(acc, acc); 
     acc = _mm_hadd_ps(acc, acc); 
     _mm_store_ss(&result[i], acc); 
    } 
} 

И вот что я придумал, как для AVX:

void multiply_matrix_by_vector_AVX(float* m, float* v, float* result, unsigned const int vector_dims) 
{ 
    size_t i, j; 

    for (i = 0; i < vector_dims; ++i) 
    { 
     __m256 acc = _mm256_setzero_ps(); 
     for (j = 0; j < vector_dims; j += 8) 
     { 
      __m256 vec = _mm256_load_ps(&v[j]); 
      __m256 mat = _mm256_load_ps(&m[j + vector_dims * i]); 
      acc = _mm256_fmadd_ps(mat, vec, acc); 
     } 
     acc = _mm256_hadd_ps(acc, acc); 
     acc = _mm256_hadd_ps(acc, acc); 
     acc = _mm256_hadd_ps(acc, acc); 
     acc = _mm256_hadd_ps(acc, acc); 

     _mm256_store_ps(&result[i], acc); 
    } 
} 

однако, AVX код аварии (Access violation reading location 0xFFFFFFFFFFFFFFFF) ,


Может ли кто-нибудь помочь мне, чтобы моя функция AVX работала правильно?

PS: размеры матриц и векторов, которые я передаю в моих функциях, всегда кратны 8. Также, массивы, которые я передаю своей функции SSE, выравниваются по 16 бит (__declspec(align(16))float* = generate_matrix(256);) и массивы, которые я передаю в AVX функция выравнивается по 32 битам (__declspec(align(32))float* = generate_matrix(256););

ответ

3

К сожалению, использование горизонтальных добавок не ограничивается до 256 бит, потому что команда (и большинство других) «отложена» - она ​​действует как две пары haddps, одна в верхней половине и одна на нижняя половина, без смешивания, так что нижняя и верхняя половины не суммируются.

Кроме того, это, конечно, еще не упакованный результат, и в этом упакованном магазине есть упорядоченное хранилище, записывающее на какой-то неуравновешенный адрес и не получится (эта ошибка немного странная, но что угодно).

Во всяком случае давайте исправим горизонтальную сумму: (не проверено)

// this part still works 
acc = _mm256_hadd_ps(acc, acc); 
acc = _mm256_hadd_ps(acc, acc); 
// this is new 
__m128 acc1 = _mm256_extractf128_ps(acc, 0); 
__m128 acc2 = _mm256_extractf128_ps(acc, 1); 
acc1 = _mm_add_ss(acc1, acc2); 
// do scalar store, obviously 
_mm_store_ss(&result[i], acc1); 

Кстати, что внутренняя петля нуждается в 10 независимых цепей (и 10 аккумуляторов), чтобы максимизировать пропускную способность на Haswell.

Смежные вопросы