Я должен сделать следующие операции AVX:
__m256 perm, func;
__m256 in = _mm256_load_ps(inPtr+x);
__m256 acc = _mm256_setzero_ps();
perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(3,2,1,0));
func = _mm256_load_ps(fPtr+0);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));
perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(2,3,0,1));
func = _mm256_load_ps(fPtr+1);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));
perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(1,0,3,2));
func = _mm256_load_ps(fPtr+2);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));
perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(0,1,2,3));
func = _mm256_load_ps(fPtr+3);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));
Это можно переписать так:
__m256 perm, func;
__m256 in = _mm256_load_ps(inPtr+x);
__m256 acc = _mm256_setzero_ps();
for(int i=0;i<4;++i)
{
perm = _mm256_shuffle_ps(in, in, _MM_SHUFFLE(3^i,2^i,1^i,0^i));
func = _mm256_load_ps(fPtr+i);
acc = _mm256_add_ps(acc, _mm256_mul_ps(perm, func));
}
Это компилируется в GCC 4.9.1, несмотря на _mm256_shuffle_ps
только принимая непосредственные целочисленные значения в качестве третьего параметра. Это означает, что i
принимается как немедленный, и, следовательно, означает, что цикл был развернут.
Поэтому мне любопытно: это гарантировано компилятором или это может вызвать ошибки компиляции при изменении флагов оптимизации или при изменении версии gcc? Как насчет использования других компиляторов (msvc, icc, clang …)
Внутреннее действительно требует немедленного значения. Компиляция работает только потому, что она была оптимизирована как константа путем развертывания цикла, а компиляция с -O0 вызывает следующую ошибку:
(…) \ Lib \ НКУ \ x86_64-w64-mingw32 \ 4.9.2 \ включать \ avxintrin.h: 331:
ошибка: последний аргумент должен быть 8-битным__mask); ^
Аналогичный случай был сообщен с ICC здесь:
https://software.intel.com/en-us/forums/intel-c-compiler/topic/287217
Других решений пока нет …