Çalıştığım bazı SSE2 ve AVX kodlarıyla ilgili garip bir sorun var. Uygulamamı cpu özelliği algılaması olan GCC'yi kullanarak uygulamamı yapıyorum. nesne dosyaları örneğin, her işlemci özelliği için ayrı bayraklarıyla inşa edilir: İlk program başlatmak zamanSSE, AVX'yi kullandıktan sonra yavaş çalışıyor
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
, ben SSE2 rutinleri olmayan SSE rutinleri üzerinde güzel bir hız artışı ile normal başına olduğunu fark (yaklaşık% 100 daha hızlı). Herhangi bir AVX rutinini çalıştırdıktan sonra, tam olarak aynı SSE2 yordamı çok daha yavaş çalışır.
Birisi bunun nedeninin ne olduğunu açıklayabilir mi?
AVX yordamını çalıştırmadan önce, tüm testler yaklaşık olarak% 80-130 daha hızlı ve ardından FPU matematiği, burada görüldüğü gibi AVX yordamından sonra, SSE yordamları çok daha yavaştır.
AVX sınama yordamlarını atlarsam, bu performans kaybını asla göremiyorum.
İşte benim rutin 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);
}
Ve aynı AVX versiyonudur.
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);
}
Ayrıca bunu hatasız algılayan valgrind ile çalıştırıyorum.
ölçülür diğer geçişler sadece 1 döngü vardır? – Gilles
@Gilles, clock_gettime (CLOCK_MONOTONIC, & start); 'önce ve sonra, sonra farkı hesaplayarak. – Geoffrey
Karışık SSEX ve AVX kodu ile meraklı sorunlarla karşılaşıyorum ... çoğunlukla Link Time code generation/etc. sorunları. Montaj dosyalarınızı arayın (ve belki de gönderin). – Christopher