SSE медленнее чем FPU? - PullRequest
       26

SSE медленнее чем FPU?

9 голосов
/ 13 января 2012

У меня есть большой кусок кода, часть тела которого содержит этот кусок кода:

result = (nx * m_Lx + ny * m_Ly + m_Lz) / sqrt(nx * nx + ny * ny + 1);

, который я векторизовал следующим образом (все уже float):

__m128 r = _mm_mul_ps(_mm_set_ps(ny, nx, ny, nx),
                      _mm_set_ps(ny, nx, m_Ly, m_Lx));
__declspec(align(16)) int asInt[4] = {
    _mm_extract_ps(r,0), _mm_extract_ps(r,1),
    _mm_extract_ps(r,2), _mm_extract_ps(r,3)
};
float (&res)[4] = reinterpret_cast<float (&)[4]>(asInt);
result = (res[0] + res[1] + m_Lz) / sqrt(res[2] + res[3] + 1);

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

  • Не векторизованная версия занимает 3750 мс
  • Векторизованная версия занимает 4050 мс
  • Установка result на 0 напрямую (и полное удаление этой части кода) сокращает весь процесс до 2500 мс

Учитывая, что векторизованная версия содержит только один набор умножений SSE (вместо четырех отдельных умножений FPU), почему она медленнее? Действительно ли FPU быстрее SSE, или здесь есть смешанная переменная?

(я нахожусь на мобильном Core i5.)

Ответы [ 3 ]

16 голосов
/ 13 января 2012

Вы тратите много времени на перемещение скалярных значений в / из регистров SSE с _mm_set_ps и _mm_extract_ps - это генерирует много инструкций, время выполнения которых значительно перевесит любую выгоду от использования _mm_mul_ps,Посмотрите на сгенерированный вывод сборки, чтобы увидеть, сколько кода генерируется в дополнение к одной инструкции MULPS.

Для правильной векторизации необходимо использовать 128-битные загрузки и сохранения SSE (_mm_load_ps/ _mm_store_ps), а затем используйте команды SSE shuffle для перемещения элементов внутри регистров, где это необходимо.

Еще один момент, на который следует обратить внимание - современные процессоры, такие как Core i5 и Core i7, имеют два скалярных FPU и могут выдавать 2умножение с плавающей запятой за тактСледовательно, потенциальная выгода от SSE для плавающей запятой одинарной точности в лучшем случае всего 2x.Легко потерять большую часть / всю эту выгоду в 2 раза, если у вас слишком много инструкций по ведению домашнего хозяйства, как здесь.

3 голосов
/ 13 января 2012

Существует несколько проблем:

  1. Вы не увидите особых преимуществ от использования инструкций SSE в таких операциях, поскольку предполагается, что инструкции SSE лучше подходят для параллельных операций (то есть умножения нескольких значенийв то же время).То, что вы сделали, это неправильное использование SSE
  2. не устанавливайте значения, используйте указатель на 1-е значение в массиве, но тогда ваши значения не находятся в массиве
  3. не извлекайтеи скопировать значения в массив.Это также злоупотребление SSE.Результат должен быть в массиве.
0 голосов
/ 13 января 2012

Я бы предположил, что у процессора есть время для вычисления первого умножения при использовании FPU при загрузке следующих значений. SSE должен сначала загрузить все значения.

...