В дополнение к SSE-copy, AVX-copy and std::copy performance. Предположим, что нам нужно векторизовать некоторый цикл следующим образом: 1) векторизовать первый цикл-пакет (который является кратным 8) через AVX. 2) остаток отрезного цикла в две партии. Векторизация партии, которая кратно 4 через SSE. 3) Обработать остаточную партию всего цикла через последовательную процедуру. Рассмотрим пример копирования массивов:Сопротивление окружающей среды SSE и AVX
#include <immintrin.h>
template<int length,
int unroll_bound_avx = length & (~7),
int unroll_tail_avx = length - unroll_bound_avx,
int unroll_bound_sse = unroll_tail_avx & (~3),
int unroll_tail_last = unroll_tail_avx - unroll_bound_sse>
void simd_copy(float *src, float *dest)
{
auto src_ = src;
auto dest_ = dest;
//Vectorize first part of loop via AVX
for(; src_!=src+unroll_bound_avx; src_+=8, dest_+=8)
{
__m256 buffer = _mm256_load_ps(src_);
_mm256_store_ps(dest_, buffer);
}
//Vectorize remainder part of loop via SSE
for(; src_!=src+unroll_bound_sse+unroll_bound_avx; src_+=4, dest_+=4)
{
__m128 buffer = _mm_load_ps(src_);
_mm_store_ps(dest_, buffer);
}
//Process residual elements
for(; src_!=src+length; ++src_, ++dest_)
*dest_ = *src_;
}
int main()
{
const int sz = 15;
float *src = (float *)_mm_malloc(sz*sizeof(float), 16);
float *dest = (float *)_mm_malloc(sz*sizeof(float), 16);
float a=0;
std::generate(src, src+sz, [&](){return ++a;});
simd_copy<sz>(src, dest);
_mm_free(src);
_mm_free(dest);
}
Правильно ли использовать SSE и AVX? Нужно ли избегать переходов AVX-SSE?
Вы можете смешать все, что вы хотите. Просто убедитесь, что у вас есть правильный флаг компилятора, чтобы заставить все SIMD-инструкции кодировать VEX. – Mysticial
@Mystical, компилятор - gcc 4.7., Flags -O2 -msse -msse2 -msse4.2 -mavx -mfpmath = sse. Это верно? – gorill
Да, это нормально. Хотя '-mavx' - это все, что вам нужно. При указании любой SIMD-опции автоматически включаются все под ним. – Mysticial