C ++ конвертировать код SSE в AVX

С помощью ВАС я использовал SSE в своем коде (пример ниже) со значительным увеличением производительности, и мне было интересно, можно ли улучшить это повышение с помощью 256-битных регистров AVX.

int result[4] __attribute__((aligned(16))) = {0};
__m128i vresult = _mm_set1_epi32(0);
__m128i v1, v2, vmax;
for (int k = 0; k < limit; k += 4) {
v1 = _mm_load_si128((__m128i *) & myVector[positionNodeId + k]);
v2 = _mm_load_si128((__m128i *) & myVector2[k]);
vmax = _mm_add_epi32(v1, v2);
vresult = _mm_max_epi32(vresult, vmax);
}
_mm_store_si128((__m128i *) result, vresult);
return max(max(max(result[0], result[1]), result[2]), result[3]);

Итак, у меня есть 3 вопроса: как можно преобразовать приведенный выше довольно простой код SSE в AVX? Какой заголовок я должен импортировать для этого? И какой флаг я должен указать моему компилятору gcc (вместо -sse4.1) для работы AVX?

Заранее спасибо. за помощь.

0

Решение

1.) This code can be easily converted to AVX2 (see below)
2.) #include <x86intrin.h>
3.) compile with -mavx2

Вам понадобится процессор с поддержкой AVX2. В настоящее время только процессоры Intel Haswell поддерживают это. У меня нет процессора Haswell (пока), поэтому я не смог протестировать код.

    int result[8] __attribute__((aligned(32))) = {0};
__m256i vresult = _mm256_set1_epi32(0);
__m256i v1, v2, vmax;

for (int k = 0; k < limit; k += 8) {
v1 = _mm256_load_si256((__m256i *) & myVector[positionNodeId + k]);
v2 = _mm256_load_si256((__m256i *) & myVector2[k]);
vmax = _mm256_add_epi32(v1, v2);
vresult = _mm256_max_epi32(vresult, vmax);
}
return horizontal_max_Vec8i(vresult);
//_mm256_store_si256((__m256i *) result, vresult);
//int mymax = result[0];
//for(int k=1; k<8; k++) {
//    if(result[k]>mymax) mymax = result[k];
//}
//return mymax;

Редактировать: Я подозреваю, что, поскольку вы используете только 64 элемента, горизонтальный максимум имеет небольшое, но не незначительное время вычисления. Я придумал horizontal_max_Vec4i функция для SSE и horizontal_max_Vec8i функция для AVX (для нее не нужен AVX2). Попробуйте заменить max(max(max(result[0], result[1]), result[2]), result[3]) с horizontal_max_Vec4i,

int horizontal_max_Vec4i(__m128i x) {
__m128i max1 = _mm_shuffle_epi32(x, _MM_SHUFFLE(0,0,3,2));
__m128i max2 = _mm_max_epi32(x,max1);
__m128i max3 = _mm_shuffle_epi32(max2, _MM_SHUFFLE(0,0,0,1));
__m128i max4 = _mm_max_epi32(max2,max3);
return _mm_cvtsi128_si32(max4);
}

int horizontal_max_Vec8i(__m256i x) {
__m128i low = _mm256_castsi256_si128(x);
__m128i high = _mm256_extractf128_si256(x,1);
return horizontal_max_Vec4i(_mm_max_epi32(low,high));
}
2

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

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