У меня странная проблема с некоторыми SSE2 и кодом AVX, над которыми я работаю. Я создаю свое приложение, используя GCC, которое обнаруживает функцию cpu. Объектные файлы построены с отдельными флагами для каждой функции центрального процессора, например:SSE работает медленно после использования AVX
g++ -c -o ConvertSamples_SSE.o ConvertSamples_SSE.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -msse
g++ -c -o ConvertSamples_SSE2.o ConvertSamples_SSE2.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -msse2
g++ -c -o ConvertSamples_AVX.o ConvertSamples_AVX.cpp -std=c++11 -fPIC -O0 -g -Wall -I./include -mavx
Когда я первый запустить программу, я считаю, что подпрограммы SSE2 являются в нормальном с хорошим повышением скорости над не являющимися рутинами SSE (примерно на 100% быстрее). После запуска любой процедуры AVX точная процедура SSE2 теперь выполняется намного медленнее.
Может кто-нибудь объяснить причину этого?
До запуска процедуры AVX все тесты примерно на 80-130% быстрее, чем математика FPU, как можно видеть здесь, после запуска процедуры AVX процедуры SSE выполняются намного медленнее.
Если я пропущу процедуры тестирования AVX, я никогда не вижу этой потери производительности.
Вот мой SSE2 рутина
void Float_S16(const float *in, int16_t *out, const unsigned int samples)
{
static float ratio = (float)Limits<int16_t>::range()/(float)Limits<float>::range();
static __m128 mul = _mm_set_ps1(ratio);
unsigned int i;
for (i = 0; i < samples - 3; i += 4, in += 4, out += 4)
{
__m128i con = _mm_cvtps_epi32(_mm_mul_ps(_mm_load_ps(in), mul));
out[0] = ((int16_t*)&con)[0];
out[1] = ((int16_t*)&con)[2];
out[2] = ((int16_t*)&con)[4];
out[3] = ((int16_t*)&con)[6];
}
for (; i < samples; ++i, ++in, ++out)
*out = (int16_t)lrint(*in * ratio);
}
И версия AVX то же самое.
void Float_S16(const float *in, int16_t *out, const unsigned int samples)
{
static float ratio = (float)Limits<int16_t>::range()/(float)Limits<float>::range();
static __m256 mul = _mm256_set1_ps(ratio);
unsigned int i;
for (i = 0; i < samples - 7; i += 8, in += 8, out += 8)
{
__m256i con = _mm256_cvtps_epi32(_mm256_mul_ps(_mm256_load_ps(in), mul));
out[0] = ((int16_t*)&con)[0];
out[1] = ((int16_t*)&con)[2];
out[2] = ((int16_t*)&con)[4];
out[3] = ((int16_t*)&con)[6];
out[4] = ((int16_t*)&con)[8];
out[5] = ((int16_t*)&con)[10];
out[6] = ((int16_t*)&con)[12];
out[7] = ((int16_t*)&con)[14];
}
for(; i < samples; ++i, ++in, ++out)
*out = (int16_t)lrint(*in * ratio);
}
Я также запускаю это через valgrind, который не обнаруживает ошибок.
Как время измеряется? – Gilles
@ Gilles, используя 'clock_gettime (CLOCK_MONOTONIC, & start);' до и после, затем вычисляя разницу. – Geoffrey
У меня возникли любопытные проблемы со смешанным кодом SSEX и AVX ..., в основном потому, что генерация кода Time Time/etc. проблемы. Посмотрите (и, возможно, опубликуйте) свои файлы сборки. – Christopher