Krokusse/common.js
- 1 year ago
- 0
- 0
SSE ( англ. Streaming SIMD Extensions , потоковое SIMD-расширение процессора) — это SIMD - ( англ. Single Instruction, Multiple Data , Одна инструкция — множество данных) набор инструкций, разработанный Intel и впервые представленный в процессорах серии Pentium III как ответ на аналогичный набор инструкций 3DNow! от AMD , который был представлен годом раньше. Первоначально названием этих инструкций было KNI — Katmai New Instructions (Katmai — название первой версии ядра процессора Pentium III ).
Технология SSE позволяла преодолеть две основные проблемы MMX : при использовании MMX невозможно было одновременно использовать инструкции сопроцессора , так как его регистры были общими с регистрами MMX, и возможность MMX работать только с целыми числами.
SSE включает в архитектуру процессора восемь 128-битных регистров и набор инструкций, работающих со скалярными и упакованными типами данных.
Преимущество в производительности достигается в том случае, когда необходимо произвести одну и ту же последовательность действий над разными данными. В таком случае блоком SSE осуществляется распараллеливание вычислительного процесса между данными.
В SSE добавлены восемь (шестнадцать для x64) 128-битных регистров, которые называются xmm0 — xmm7 (-xmm15).
Каждый регистр может содержать четыре 32-битных значения с плавающей запятой одинарной точности.
Команды для чисел с плавающей точкой
Команды для целых чисел
Другие команды
Следующий пример демонстрирует перемножение четырёх пар чисел с плавающей точкой одной инструкцией mulps : (Программа написана на языке ANSI C++ с использованием ассемблерной вставки __asm и инструкций ассемблера для работы с SSE, аргументы записаны согласно стандарту Intel, а не AT&T)
__declspec(align(16)) float a[4] = { 300.0, 4.0, 4.0, 12.0 };
__declspec(align(16)) float b[4] = { 1.5, 2.5, 3.5, 4.5 };
__asm {
movups xmm0, a ; // поместить 4 переменные с плавающей точкой из a в регистр xmm0
movups xmm1, b ; // поместить 4 переменные с плавающей точкой из b в регистр xmm1
mulps xmm0, xmm1 ; // перемножить пакеты плавающих точек: xmm0 = xmm0 * xmm1
; // xmm00 = xmm10 * xmm00
; // xmm01 = xmm11 * xmm01
; // xmm02 = xmm12 * xmm02
; // xmm03 = xmm13 * xmm03
movups a, xmm0 ; // выгрузить результаты из регистра xmm0 по адресам a
};
Тот же пример, но ассемблерная вставка asm выполнена в стандарте AT&T (GNU Assembler)
float a[4] = { 300.0, 4.0, 4.0, 12.0 };
float b[4] = { 1.5, 2.5, 3.5, 4.5 };
__asm__ volatile
(
"movups %[a], %%xmm0\n\t" // поместить 4 переменные с плавающей точкой из a в регистр xmm0
"movups %[b], %%xmm1\n\t" // поместить 4 переменные с плавающей точкой из b в регистр xmm1
"mulps %%xmm1, %%xmm0\n\t" // перемножить пакеты плавающих точек: xmm0 = xmm0 * xmm1
// xmm00 = xmm00 * xmm10
// xmm01 = xmm01 * xmm11
// xmm02 = xmm02 * xmm12
// xmm03 = xmm03 * xmm13
"movups %%xmm0, %[a]\n\t" // выгрузить результаты из регистра xmm0 по адресам a
:
: [a]"m"(*a), [b]"m"(*b)
: "%xmm0", "%xmm1"
);