Введение
Комплекты дополнительных инструкций для процессоров Intel SIMD, представленные Intel
SSE2 (Streaming SIMD Extensions 2) – один из комплектов дополнительных инструкций для процессоров Intel SIMD (Single Instruction, Multiple Data), представленных Intel вместе с первой версией Pentium 4 в 2000 году. Инструкции SSE2 позволяют использовать XMM (SIMD) регистры на процессорах с архитектурой набора инструкций x86. Эти регистры могут загружать до 128 бит данных и одновременно выполнять инструкции, такие как векторное сложение и умножение. SSE2 представил инструкции для вычислений с плавающей точкой двойной точности в дополнение к инструкциям для вычислений с плавающей точкой одинарной точности и целочисленным инструкциям, присутствующим в SSE. SSE2 расширяет более ранний набор инструкций SSE, добавляя 144 новые инструкции к предыдущим 70. SSE2 предназначен для полной замены MMX – набора инструкций SIMD, используемого в процессорах архитектуры IA-32. Конкурирующий производитель чипов AMD добавил поддержку SSE2 с выпуском линейки Opteron и Athlon 64 64-битных процессоров AMD64 в 2003 году. SSE2 был расширен для создания SSE3 в 2004 году и повторно расширен для создания SSE4 в 2006 году.
Особенности
Большинство инструкций SSE2 реализуют целочисленные векторные операции, также присутствующие в MMX. Вместо регистров MMX они используют регистры XMM, которые шире и позволяют значительно повысить производительность в специализированных приложениях. Другим преимуществом замены MMX на SSE2 является устранение штрафа за переключение режимов при выполнении инструкций x87, характерного для MMX, поскольку он использует то же адресное пространство, что и FPU x87. SSE2 также дополняет векторные операции с плавающей точкой набора инструкций SSE, добавляя поддержку типа данных двойной точности. Другие расширения SSE2 включают набор инструкций управления кэшем, предназначенных главным образом для минимизации загрязнения кэша при обработке бесконечных потоков данных, и широкий набор инструкций преобразования числовых форматов. Реализация SSE2 компанией AMD на платформе AMD64 (x86 64) включает в себя восемь дополнительных регистров, удваивая их общее количество до 16 (XMM0–XMM15). Эти дополнительные регистры видны только в 64-битном режиме. Intel переняла эти дополнительные регистры в рамках поддержки архитектуры x86 64 (или, как это называет Intel, "Intel 64") в 2004 году.
Различия между x87 FPU и SSE2
Инструкции FPU (x87) обеспечивают более высокую точность, вычисляя промежуточные результаты с точностью 80 бит по умолчанию, чтобы минимизировать ошибку округления в численно неустойчивых алгоритмах (см. обоснование проектирования IEEE 754 и ссылки в нем). Однако, x87 FPU является скалярным устройством, в то время как SSE2 может обрабатывать небольшой вектор операндов параллельно. При переносе кода, разработанного для x87, на SSE2 с двойной точностью, некоторые комбинации математических операций или наборов входных данных могут приводить к измеримому числовому расхождению, что может стать проблемой в воспроизводимых научных вычислениях, например, если результаты расчетов необходимо сравнивать с результатами, полученными на другой аппаратной архитектуре. Связанная проблема заключается в том, что исторически языковые стандарты и компиляторы были непоследовательны в обработке 80-битных регистров x87, реализующих переменные двойной расширенной точности, по сравнению с форматами двойной и одинарной точности, реализованными в SSE2: округление промежуточных значений расширенной точности до двойной точности не было полностью определено и зависело от деталей реализации, таких как момент сброса регистров в память.
Различия между MMX и SSE2
SSE2 расширяет инструкции MMX для работы с регистрами XMM. Поэтому возможно преобразовать весь существующий MMX-код в эквивалент SSE2. Поскольку регистр SSE2 вдвое длиннее регистра MMX, счетчики циклов и доступ к памяти могут потребовать изменений для учета этого. Однако доступны 8-байтовые загрузки и сохранения в XMM, поэтому это не является строго обязательным. Хотя одна инструкция SSE2 может обрабатывать вдвое больше данных, чем инструкция MMX, прирост производительности может быть незначительным. Две основные причины: доступ к данным SSE2 в памяти, не выровненной по 16-байтовой границе, может привести к значительным потерям производительности, а пропускная способность инструкций SSE2 в более старых реализациях x86 была вдвое ниже, чем у инструкций MMX. Intel решила первую проблему, добавив инструкцию в SSE3 для уменьшения накладных расходов при доступе к невыровненным данным и повышения общей производительности при загрузке невыровненных данных, а вторую – расширив исполнительный механизм в своей микроархитектуре Core в Core 2 Duo и более поздних продуктах. Поскольку регистровые файлы MMX и x87 являются псевдонимами друг друга, использование MMX может помешать правильной работе инструкций x87. После использования MMX программист должен использовать инструкцию `emms` (C: mm empty) для восстановления работы с регистровым файлом x87. На некоторых операционных системах x87 используется не очень часто, но может по-прежнему применяться в некоторых критических областях, таких как `pow`, где требуется повышенная точность. В таких случаях поврежденное состояние чисел с плавающей точкой, вызванное отсутствием инструкции `emms`, может оставаться незамеченным в течение миллионов инструкций, прежде чем в конечном итоге привести к сбою подпрограммы чисел с плавающей точкой и возврату NaN. Поскольку проблема не проявляется локально в MMX-коде, поиск и исправление ошибки может занять много времени. Поскольку SSE2 не имеет этой проблемы и обычно обеспечивает гораздо более высокую пропускную способность и большее количество регистров в 64-битном коде, его следует предпочесть практически для всех задач векторизации.
Использование компилятора
Когда SSE2 был представлен в 2000 году, он не поддерживался инструментами разработки программного обеспечения. Например, для использования SSE2 в проекте Microsoft Visual Studio программисту приходилось либо вручную писать инлайн-ассемблер, либо импортировать объектный код из внешнего источника. Позже Visual C++ Processor Pack добавил поддержку SSE2 в Visual C++ и MASM. Компилятор Intel C++ может автоматически генерировать код SSE4, SSSE3, SSE3, SSE2 и SSE, не используя ручное кодирование ассемблера. Начиная с GCC 3, GCC может автоматически генерировать скалярный код SSE/SSE2, если целевая архитектура поддерживает эти инструкции. Автоматическая векторизация для SSE/SSE2 была добавлена начиная с GCC 4. Sun Studio Compiler Suite также может генерировать инструкции SSE2 при использовании флага компилятора xvector=simd. Начиная с Microsoft Visual C++ 2012, опция компилятора для генерации инструкций SSE2 включена по умолчанию.