Я выполняю разрозненное чтение 8-битных данных из файла (устранение чередования 64-канального волнового файла). Затем я объединяю их в один поток байтов. У меня проблема с восстановлением данных для записи.
Обычно я читаю 16 байтов, а затем собираю их в одну переменную __m128i, а затем использую _mm_stream_ps для записи значения обратно в память. Однако у меня есть некоторые странные результаты производительности.
В моей первой схеме я использую встроенную функцию _mm_set_epi8 для установки моего __m128i следующим образом:
const __m128i packedSamples = _mm_set_epi8( sample15, sample14, sample13, sample12, sample11, sample10, sample9, sample8,
sample7, sample6, sample5, sample4, sample3, sample2, sample1, sample0 );
По сути, я оставляю все это на усмотрение компилятора, чтобы решить, как оптимизировать его, чтобы обеспечить лучшую производительность. Это дает худшую производительность. МОЙ тест длится ~ 0,195 секунды.
Во-вторых, я попытался объединиться, используя 4 _mm_set_epi32 инструкции, а затем упаковав их:
const __m128i samples0 = _mm_set_epi32( sample3, sample2, sample1, sample0 );
const __m128i samples1 = _mm_set_epi32( sample7, sample6, sample5, sample4 );
const __m128i samples2 = _mm_set_epi32( sample11, sample10, sample9, sample8 );
const __m128i samples3 = _mm_set_epi32( sample15, sample14, sample13, sample12 );
const __m128i packedSamples0 = _mm_packs_epi32( samples0, samples1 );
const __m128i packedSamples1 = _mm_packs_epi32( samples2, samples3 );
const __m128i packedSamples = _mm_packus_epi16( packedSamples0, packedSamples1 );
Это несколько улучшает производительность. Мой тест теперь выполняется за ~ 0,15 секунды. Кажется нелогичным, что при этом производительность улучшится, поскольку я полагаю, что именно это и делает _mm_set_epi8 в любом случае ...
Моя последняя попытка состояла в том, чтобы использовать немного кода, который я имею, сделать четыре CC по старинке (со сдвигами и ор), а затем поместить их в __m128i, используя один _mm_set_epi32.
const GCui32 samples0 = MakeFourCC( sample0, sample1, sample2, sample3 );
const GCui32 samples1 = MakeFourCC( sample4, sample5, sample6, sample7 );
const GCui32 samples2 = MakeFourCC( sample8, sample9, sample10, sample11 );
const GCui32 samples3 = MakeFourCC( sample12, sample13, sample14, sample15 );
const __m128i packedSamples = _mm_set_epi32( samples3, samples2, samples1, samples0 );
Это дает еще лучшую производительность. Потребовалось ~ 0,135 секунды, чтобы запустить мой тест. Я действительно начинаю путаться.
Итак, я попробовал простую систему чтения байтов с записью байтов, и она немного быстрее, чем даже последний метод.
Так что происходит? Мне все кажется нелогичным.
Я обдумал идею, что задержки происходят на _mm_stream_ps, потому что я передаю данные слишком быстро, но тогда я бы получал точно такие же результаты, что бы я ни делал. Возможно ли, что первые 2 метода означают, что 16 нагрузок не могут распределяться через цикл, чтобы скрыть задержку? Если так, то почему? Конечно, встроенная функция позволяет компилятору оптимизировать как и когда угодно. Я подумал, что в этом весь смысл ... Также наверняка выполнение 16 операций чтения и 16 операций записи будет намного медленнее, чем 16 операций чтения и 1 записи с использованием множества SSE-жонглирования. инструкции ... После всего чтения и записи, которые являются медленным битом!
Любой, у кого есть идеи, что происходит, будет высоко оценен! : D
Редактировать: В дополнение к комментарию ниже, я перестал предварительно загружать байты как константы и изменил это на:
const __m128i samples0 = _mm_set_epi32( *(pSamples + channelStep3), *(pSamples + channelStep2), *(pSamples + channelStep1), *(pSamples + channelStep0) );
pSamples += channelStep4;
const __m128i samples1 = _mm_set_epi32( *(pSamples + channelStep3), *(pSamples + channelStep2), *(pSamples + channelStep1), *(pSamples + channelStep0) );
pSamples += channelStep4;
const __m128i samples2 = _mm_set_epi32( *(pSamples + channelStep3), *(pSamples + channelStep2), *(pSamples + channelStep1), *(pSamples + channelStep0) );
pSamples += channelStep4;
const __m128i samples3 = _mm_set_epi32( *(pSamples + channelStep3), *(pSamples + channelStep2), *(pSamples + channelStep1), *(pSamples + channelStep0) );
pSamples += channelStep4;
const __m128i packedSamples0 = _mm_packs_epi32( samples0, samples1 );
const __m128i packedSamples1 = _mm_packs_epi32( samples2, samples3 );
const __m128i packedSamples = _mm_packus_epi16( packedSamples0, packedSamples1 );
и это улучшило производительность до ~ 0,143 секунды. Sitll не так хорош, как прямая реализация C ...
Редактировать еще раз: лучшее, что я пока получаю, это
// Load the samples.
const GCui8 sample0 = *(pSamples + channelStep0);
const GCui8 sample1 = *(pSamples + channelStep1);
const GCui8 sample2 = *(pSamples + channelStep2);
const GCui8 sample3 = *(pSamples + channelStep3);
const GCui32 samples0 = Build32( sample0, sample1, sample2, sample3 );
pSamples += channelStep4;
const GCui8 sample4 = *(pSamples + channelStep0);
const GCui8 sample5 = *(pSamples + channelStep1);
const GCui8 sample6 = *(pSamples + channelStep2);
const GCui8 sample7 = *(pSamples + channelStep3);
const GCui32 samples1 = Build32( sample4, sample5, sample6, sample7 );
pSamples += channelStep4;
// Load the samples.
const GCui8 sample8 = *(pSamples + channelStep0);
const GCui8 sample9 = *(pSamples + channelStep1);
const GCui8 sample10 = *(pSamples + channelStep2);
const GCui8 sample11 = *(pSamples + channelStep3);
const GCui32 samples2 = Build32( sample8, sample9, sample10, sample11 );
pSamples += channelStep4;
const GCui8 sample12 = *(pSamples + channelStep0);
const GCui8 sample13 = *(pSamples + channelStep1);
const GCui8 sample14 = *(pSamples + channelStep2);
const GCui8 sample15 = *(pSamples + channelStep3);
const GCui32 samples3 = Build32( sample12, sample13, sample14, sample15 );
pSamples += channelStep4;
const __m128i packedSamples = _mm_set_epi32( samples3, samples2, samples1, samples0 );
_mm_stream_ps( pWrite + 0, *(__m128*)&packedSamples );
Это дает мне обработку в ~ 0,095 секунды, что значительно лучше. Похоже, я не могу сблизиться с SSE ... Я все еще смущен этим, но ... хм-ха.