Они используются в
- Операции с плавающей запятой
- Операции с несколькими данными одновременно
вам нужно использовать 2 64битовые операции для выполнения математических операций над 128-битным числом
Нет, они не предназначены для этой цели, и их нельзя легко использовать для 128-битных чисел.Намного быстрее добавить 128-битное число только с двумя инструкциями: add rax, rbx; adc rdx, rcx
вместо тонны инструкций при работе с регистрами XMM.См.
Что касается их использования, то во-первых, они используются для скалярных операций с плавающей точкой .Так что если у вас есть float
или double
в C или C ++, то они, скорее всего, будут храниться в нижней части регистров XMM и обрабатываться инструкциями, заканчивающимися на ss
( скалярное одиночное ) илиsd
( скалярное двойное )
На самом деле существует еще один набор из восьми 80-битных ST(x)
регистров, который был доступен с сопроцессором x87 дляделать математику с плавающей точкой.Однако они медленные и менее предсказуемые.Медленно, потому что операции выполняются с высокой точностью по умолчанию, что по сути требует больше работы , а также требует сохранения, а затем загружает до округления для уменьшения точности при необходимости.Непредсказуемо также из-за высокой точности.Поначалу это может показаться странным, но это легко объяснить, например, переполнение или недополнение некоторых операций с точностью float
или double
, но не с точностью long double
.Это приводит к множеству ошибок или неожиданным результатам в 32- и 64-битной сборке 1
Вот пример с плавающей запятой для обоих наборов регистров
// f = x/z + y*z
x87:
fld dword ptr [esp + 12]
fld st(0)
fdivr dword ptr [esp + 4]
fxch st(1)
fmul dword ptr [esp + 8]
faddp st(1)
ret
SSE:
divss xmm0, xmm2
mulss xmm1, xmm2
addss xmm0, xmm1
ret
AVX:
vdivss xmm0, xmm0, xmm2
vmulss xmm1, xmm1, xmm2
vaddss xmm0, xmm0, xmm1
ret
Переход на более быстрые и согласованные регистры SSE является одной из причин, по которой тип 80-битной расширенной точности long double
больше не доступен в MSVC
Затем Intel представила MMX набор команд для SIMD операций, который использует те же самые регистры ST(x)
с новым именем MMX
.MMX может означать Multiple Math eXtension или Matrix Math eXtension , но ИМХО это наиболее вероятно или MultiMedia eXtension , так как мультимедиа и Интернет приобретают все большее значение в то время,В мультимедийных решениях вам очень часто приходится выполнять одни и те же операции с каждым пикселем, текселем, сэмплом ... вот так
for (int i = 0; i < 100000; ++i)
{
A[i] = B[i] + C[i];
D[i] = E[i] * F[i];
}
Вместо того, чтобы работать с каждым элементом по отдельности, мы можем ускорить работу с помощью нескольких элементоввовремя.Вот почему люди изобрели SIMD.С MMX вы можете увеличить яркость 8-пиксельных каналов или громкость четырех 16-битных сэмплов одновременно ... Операции над одним элементом называются scalar , а полный регистр называется вектором,который представляет собой набор скалярных значений
Из-за недостатков MMX (таких как повторное использование ST
регистров или отсутствие поддержки с плавающей запятой), когда расширенный набор инструкций SIMD установлен с помощью Потоковые расширения SIMD(SSE) Intel решила предоставить им совершенно новый набор регистров с именем XMM, который в два раза длиннее (128 бит), поэтому теперь мы можем работать с 16 байтами одновременно.И он также поддерживает несколько операций с плавающей точкой одновременно.Затем Intel удлинила XMM до 256-битного YMM в Advanced Vector Extensions (AVX) и еще раз удвоила длину в AVX-512 (на этот раз она также увеличила количество регистров).до 32 в 64-битном режиме).Теперь вы можете работать с шестнадцатью 32-битными целыми числами за один раз
Из вышесказанного вы можете понять вторую и наиболее важную роль этих регистров: выполнение операций над несколькими данными параллельно с одной инструкцией .Например, в SSE4 был представлен набор инструкций для работы со строками C .Теперь вы можете считать длину строки, находить подстроки ... намного быстрее, проверяя несколько байтов одновременно.Вы также можете копировать или сравнивать память намного быстрее.Современные реализации memcpy
перемещают 16, 32 или 64 байта за раз, в зависимости от наибольшей ширины регистра, а не один за другим, как в простейшем решении C.
К сожалению, компиляторы все еще плохо конвертируют изскалярный код в параллельный код, поэтому в большинстве случаев нам приходится им помогать, хотя автоматическая векторизация все еще совершенствуется и совершенствуется
Ввиду важности SIMD, в настоящее время практически любая высокопроизводительная архитектура имеет собственную версию SIMD, такую как Altivec на PowerPC или Neon на ARM.
1 Некоторые примеры: