Где инструкции SSE превосходят обычные инструкции

Где инструкции x86-64 SSE (векторные инструкции) превосходят обычные инструкции. Потому что я вижу, что частые загрузки и накопления, необходимые для выполнения инструкций SSE, сводят на нет любой выигрыш, который мы получаем из-за векторного вычисления. Так может кто-нибудь дать мне пример кода SSE, где он работает лучше, чем обычный код.

Возможно, потому что я передаю каждый параметр отдельно, как это...

__m128i a = _mm_set_epi32(pa[0], pa[1], pa[2], pa[3]);
__m128i b = _mm_set_epi32(pb[0], pb[1], pb[2], pb[3]);
__m128i res = _mm_add_epi32(a, b);

for( i = 0; i < 4; i++ )
 po[i] = res.m128i_i32[i];

Разве нет способа, которым я могу передать все 4 целых числа за один раз, я имею в виду передать все 128 байтов pa за один раз? И назначить res.m128i_i32 в po за один раз?

1 ответ

Решение

Обобщение комментариев в ответ:

Вы попали в ту же ловушку, в которую попадает большинство новичков. По сути, в вашем примере есть две проблемы:

  1. Вы злоупотребляете _mm_set_epi32(),
  2. У вас очень низкое соотношение вычислений к нагрузке. (От 1 до 3 в вашем примере)

_mm_set_epi32() это очень дорогая присущая. Хотя его удобно использовать, он не компилируется ни в одну инструкцию. Некоторые компиляторы (такие как VS2010) могут генерировать очень плохо работающий код при использовании _mm_set_epi32(),

Вместо этого, поскольку вы загружаете смежные блоки памяти, вы должны использовать _mm_load_si128(), Это требует, чтобы указатель был выровнен до 16 байтов. Если вы не можете гарантировать это выравнивание, вы можете использовать _mm_loadu_si128() - но с потерей производительности. В идеале, вы должны правильно выровнять свои данные, чтобы не прибегать к использованию _mm_loadu_si128(),


Будучи по-настоящему эффективным с SSE, вы также захотите максимизировать соотношение вычислений и нагрузки. Цель, по которой я стреляю, - это 3 - 4 арифметических инструкции на доступ к памяти. Это довольно высокое соотношение. Как правило, вы должны изменить код или изменить алгоритм для его увеличения. Объединение проходов по данным является распространенным подходом.

Развертывание циклов часто необходимо для максимизации производительности, когда у вас большие тела циклов с длинными цепочками зависимостей.


Некоторые примеры вопросов SO, которые успешно используют SSE для достижения ускорения.

Другие вопросы по тегам