Sse 4 2 на каких процессорах

Обновлено: 05.07.2024

SSE4 ( Streaming SIMD Extensions 4 ) - это набор инструкций ЦП SIMD, используемый в микроархитектуре Intel Core и AMD K10 (K8L) . Об этом было объявлено 27 сентября 2006 г. на Форуме разработчиков Intel осенью 2006 г. с расплывчатыми деталями в официальном документе ; более точные детали 47 инструкций стали доступны в презентации на форуме разработчиков Intel весной 2007 года в Пекине . SSE4 полностью совместим с программным обеспечением, написанным для предыдущих поколений микропроцессоров с архитектурой Intel 64 и IA-32. Все существующее программное обеспечение продолжает работать правильно без изменений на микропроцессорах, которые включают SSE4, а также при наличии существующих и новых приложений, которые включают SSE4.

СОДЕРЖАНИЕ

Подмножества SSE4

Intel SSE4 состоит из 54 инструкций. Подмножество, состоящее из 47 инструкций, которое в некоторой документации Intel называется SSE4.1 , доступно в Penryn . Кроме того, SSE4.2 , второе подмножество , состоящее из 7 оставшихся инструкций, является первым доступным в Nehalem основанного Core i7 . Intel считает, что отзывы разработчиков сыграли важную роль в разработке набора инструкций.

Начиная с процессоров на базе Barcelona , AMD представила набор инструкций SSE4a , который имеет 4 инструкции SSE4 и 4 новые инструкции SSE. Этих инструкций нет в процессорах Intel, поддерживающих SSE4.1, а процессоры AMD только начали поддерживать Intel SSE4.1 и SSE4.2 (полный набор инструкций SSE4) в процессорах FX на базе Bulldozer . В SSE4a также была введена функция несовпадения SSE, что означало, что невыровненные инструкции загрузки выполнялись так же быстро, как выровненные версии на выровненных адресах. Это также позволило отключить проверку выравнивания при доступе к памяти ненагруженных операций SSE. Позже Intel представила аналогичные улучшения скорости невыровненного SSE в своих процессорах Nehalem, но не вводила несогласованный доступ с помощью ненагруженных инструкций SSE до AVX .

Путаница в названии

То, что сейчас известно как SSSE3 (Supplemental Streaming SIMD Extensions 3), представленное в линейке процессоров Intel Core 2 , называлось SSE4 в некоторых СМИ, пока Intel не придумала прозвище SSSE3. Компания Intel, получившая внутреннее название Merom New Instructions, изначально не планировала давать им особое название, что подверглось критике со стороны некоторых журналистов. В конце концов Intel устранила путаницу и зарезервировала имя SSE4 для своего следующего расширения набора инструкций.

Intel использует маркетинговый термин HD Boost для обозначения SSE4.

Новые инструкции

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

Некоторые из этих инструкций выполняются одноцикловым механизмом перемешивания в Penryn. (Операции перемешивания переупорядочивают байты в регистре.)

Пользователи некоторых старых компьютеров все чаще обнаруживают, что часть новых программ и компьютерных игр больше не работает на их системах. При чем это не зависит от версии или разрядности операционной системы. Ограничения находятся на аппаратном уровне и связаны с поддержкой инструкций SSE 4.1 и SSE 4.2. В данной статье мы расскажем, что это такое и какие процессоры поддерживают SSE 4.1 и SSE 4.2.

Что такое SSE 4.1 и SSE 4.2

SSE 4 – это набор инструкций, который применяется в процессорах Intel и AMD. Впервые о данном наборе инструкций стало известно в конце 2006 года на форуме для разработчиков Intel, а первые процессоры с его поддержкой появились в 2008 году.

Набор SSE 4 включает в себя 54 новых инструкций, 47 из которых относятся SSE 4.1 и еще 7 к SSE 4.2. Данные инструкции включают в себя улучшенные целочисленные операции, операции с плавающей точкой, операции с плавающей точкой одинарной точности, упаковочные операции DWORD и QWORD, быстрые регистровые операции, операции для работы с памятью, а также операции со строками.

Использование данных новых инструкций позволяет значительно повысить производительность программ. Например, такие программы DivX 6.7 и VirtualDub 1.7.2 показывают рост производительности на 49%, а TMPGEncoder Xpress 4.4 на 42%.

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

В результате многие современные игры и программы отказываются запускаться на старых компьютерах. Например, наличия SSE 4.1 или 4.2 требуют такие игры как No Man Sky, Dishonored 2, Far Cry 5 или Mafia 3. В некоторых случаях, эту проблему можно решить с помощью программного эмулятора, но это приводит к значительному снижению производительности.

Процессоры, поддерживающие SSE 4.1 и SSE 4.2

Практически все современные процессоры поддерживают инструкции SSE 4.1 и SSE 4.2. В настольных процессорах Intel поддержка SSE 4.1 появилась в архитектуре Penryn (процессоры Core 2 Duo, Core 2 Quad), а поддержка SSE 4.2 в архитектуре Nehalem (процессоры Intel Core 1-поколения). Полная же поддержка инструкций SSE 4.2 (включая POPCNT и LZCNT) доступна начиная с архитектуры Haswell (процессоры Intel Core 4-поколения). Более подробная информация о поддержке в таблице внизу.

Микроархитектура Intel Процессоры Поддержка инструкций
Silvermont

В настольных процессорах AMD сначала появилась поддержка собственного набора инструкций SSE4a, который отсутствовал в процессорах Intel. Но, уже начиная микроархитектуры Bulldozer (FX) была внедрена поддержка SSE 4.1 и SSE 4.2 (включая инструкции POPCNT и LZCNT). Последовавшая в дальнейшем микроархитектура Zen (Ryzen) также в полной мере поддерживает SSE 4.1 и SSE 4.2. Более подробная информация о поддержке в таблице внизу.

Микроархитектура AMD Процессоры Поддержка инструкций
K10

Как узнать, что процессор поддерживает SSE 4.1 и SSE 4.2

Среди прочего, с помощью CPU-Z можно проверить наличие поддержки инструкций SSE 4.1 и SSE 4.2. Для этого нужно просто запустить CPU-Z и изучить строку « Instructions » на вкладке «CPU ».

набор инструкций в cpu-z

Если процессора на руках пока нет, то можно просто поискать скриншот CPU-Z в любой поисковой системе, например, в Google. Для этого нужно ввести поисковый запрос « cpu-z название процессора » и перейти к просмотру картинок.

поиск скриншота cpu-z

Таким образом можно найти информацию практически о любом современном процессоре.

SSE4 (SSE4.1 + SSE4.2) - набор из 54 команд, разработанных компанией Intel для повышения эффективности процессора, которые вслед за SSE, SSE2, SSE3 и SSSE3 стали продолжением развития технологии SIMD (Single Instruction Multiple Data - "одна инструкция - множество данных").

Не следует путать SSE4, с разработанными компанией AMD инструкциями SSE4A (это не одно и то же).

Инструкции SSE4 были анонсированы осенью 2006 года и впервые использованы в процессорах Intel с ядром Penryn. Но в Penryn были реализованы не 54, а только 47 инструкций (SSE4.1). Позже было добавлено еще 7 инструкций (SSE4.2).

Полный набор из 54 команд (SSE4.1 + SSE4.2) был реализован в процессорах Intel архитектуры Nehalem, начало производства которых приходится на осень 2008 года.

• SSE4.1 включает 47 команд, расширяющих возможности 32x32-битных умножений, обработки массивов структур, операций сопряжения, сравнения и преобразования упакованных данных, округления, вставки и извлечения между регистрами и т.д.

В целом, инструкции SSE4.1 в значительной степени повышают эффективность процессоров при компиляторной векторизации обработки данных, работе с трехмерной графикой и в играх, обработке изображений, видеоинформации и другого мультимедийного контента.

• SSE4.2 включает 7 команд обработки строк, подсчета CRC32 и популяции единичных бит, а также работы с векторными примитивами. Эти инструкции повышают производительность при сканировании вирусов, поиска текста, строковой обработки библиотек (ZLIB, базы данных и др.).


Технологии и инструкции, используемые в процессорах

Люди обычно оценивают процессор по количеству ядер, тактовой частоте, объему кэша и других показателях, редко обращая внимание на поддерживаемые им технологии.

Отдельные из этих технологий нужны только для решения специфических заданий и в "домашнем" компьютере вряд ли когда-нибудь понадобятся. Наличие же других является непременным условием работы программ, необходимых для повседневного использования.

Так, полюбившийся многим браузер Google Chrome не работает без поддержки процессором SSE2. Инструкции AVX могут в разы ускорить обработку фото- и видеоконтента. А недавно один мой знакомый на достаточно быстром Phenom II (6 ядер) не смог запустить игру Mafia 3, поскольку его процессор не поддерживает инструкции SSE4.2.

Если аббревиатуры SSE, MMX, AVX, SIMD вам ни о чем не говорят и вы хотели бы разобраться в этом вопросе, изложенная здесь информация станет неплохим подспорьем.


Таблица совместимости процессоров и материнских плат AMD

Одной из особенностей компьютеров на базе процессоров AMD, которой они выгодно отличаются от платформ Intel, является высокий уровень совместимости процессоров и материнских плат. У владельцев относительно не старых настольных систем на базе AMD есть высокие шансы безболезненно "прокачать" компьютер путем простой замены процессора на "камень" из более новой линейки или же флагман из предыдущей.

Если вы принадлежите к их числу и задались вопросом "апгрейда", эта небольшая табличка вам в помощь.


Сравнение процессоров

В таблицу можно одновременно добавить до 6 процессоров, выбрав их из списка (кнопка "Добавить процессор"). Всего доступно больше 2,5 тыс. процессоров Intel и AMD.

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

Дополнительные рекомендации по использованию таблицы можно найти внизу страницы.


Спецификации процессоров

В этой базе собраны подробные характеристики процессоров Intel и AMD. Она содержит спецификации около 2,7 тысяч десктопных, мобильных и серверных процессоров, начиная с первых Пентиумов и Атлонов и заканчивая последними моделями.

Информация систематизирована в алфавитном порядке и будет полезна всем, кто интересуется компьютерной техникой.

Таблица содержит информацию о почти 2 тыс. процессоров и будет весьма полезной людям, интересующимся компьютерным "железом". Положение каждого процессора в таблице определяется уровнем его быстродействия в синтетических тестах (расположены по убыванию).

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

Для получения подробной информации о любом процессоре достаточно нажать на его название.


Как проверить стабильность процессора

Проверка стабильности работы центрального процессора требуется не часто. Как правило, такая необходимость возникает при приобретении компьютера, разгоне процессора (оверлокинге), при возникновении сбоев в работе компьютера, а также в некоторых других случаях.

В статье описан порядок проверки процессора при помощи программы Prime95, которая, по мнению многих экспертов и оверлокеров, является лучшим средством для этих целей.



ПОКАЗАТЬ ЕЩЕ

Это продолжение цикла статей о том, как я занимался оптимизацией и получил самый быстрый ресайз на современных x86 процессорах. В каждой статье я рассказываю часть истории, и надеюсь подтолкнуть еще кого-то заняться оптимизацией своего или чужого кода. В предыдущих сериях:

В прошлый раз мы получили ускорение в среднем в 2,5 раза без изменения подхода. В этот раз я покажу, как применять SIMD-подход и получить ускорение еще в 3,5 раза. Конечно, применение SIMD для обработки графики не является ноу-хау, можно даже сказать, что SIMD был придуман для этого. Но на практике очень мало разработчиков используют его даже в задачах обработки изображений. Например, довольно известные и распространенные библиотеки ImageMagick и LibGD написаны без использования SIMD. Отчасти так происходит потому, что SIMD-подход объективно сложнее и не кроссплатформенный, а отчасти потому, что по нему мало информации. Довольно просто найти азы, но мало детальных материалов и разбора реальных задач. От этого на Stack Overflow очень много вопросов буквально о каждой мелочи: как загрузить данные, как распаковать, запаковать. Видно, что всем приходится набивать шишки самостоятельно.

Что же такое SIMD

Смело пропускайте этот раздел, если уже знакомы с основами. SIMD означает singe instruction, multiple data (одна команда, множество данных). Такой подход позволяет объединить несколько одинаковых операций в одну. Набор данных, над которым выполняется операция, называется вектор.


В большинстве случаев на современных процессорах SIMD-инструкции выполняются за столько же тактов, за сколько их скалярные аналоги. Т.е. теоретически при переходе на SIMD можно рассчитывать на ускорение в 2, 4, 8, 16 и даже 32 раза, в зависимости от используемых типов данных и наборов команд. На практике выходит по-разному. Во-первых, даже в векторизованном коде часть кода остается скалярным. Во-вторых, часто для векторных операций данные нужно подготовить: распаковать и запаковать. Как правило, запаковка и распаковка данных — это самое сложное при написании SIMD-кода. В-третьих, SIMD-инструкции не являются точной копией обычных: для каких-то операций есть специфичные инструкции, хорошо решающие стоящую задачу, а для других задач нужных инструкций не оказывается. Например для нахождения минимального и максимального значений есть отдельные SIMD-инструкции, работающие без условных переходов. А вот целочисленного векторного деления в процессорах x86 просто нет.

  • Целые числа по 8 бит (со знаком или без)
  • Целые числа по 16 бит (со знаком или без)
  • Целые числа по 32 бита (со знаком или без)
  • Целые числа по 64 бита (со знаком или без)
  • Числа с плавающей точкой одинарной точности, 32 бита
  • Числа с плавающей точкой двойной точности, 64 бита

Все векторные регистры одинаковые и не знают, какого типа данные в них находятся. Интерпретация зависит только от инструкции, которая работает с регистром. Соответственно, большинство инструкций имеют разновидности для работы с данными разных типов. Инструкции могут принимать данные одного типа, а выдавать другого. Если вы знакомы с ассемблером, это чем-то напоминает то, как работают обычные регистры: вы можете записать что-то в 32-битный регистр eax , а потом работать с его 16-битной частью ax .

Выбор подходящего расширения команд

Первые SIMD-инструкции появились в процессоре Intel Pentium MMX. Собственно MMX — это и есть название расширения команд. Этот набор был настолько важным, что Intel вынесла его в название процессора. С помощью MMX я когда-то давно писал простенькие алгоритмы вроде смешивания двух изображений или суперсемплинга. Писал на Дельфи, но чтобы использовать MMX, приходилось спускаться на уровень ниже и делать вставки на ассемблере.

С тех пор я не слишком следил за развитием процессорных команд и связанных с ними средств разработки. Поэтому, когда я недавно снова взялся за SIMD, был приятно удивлен. Нет, компилятор все еще не способен автоматически применять SIMD-инструкции в более-менее сложных случаях. А если и способен, то обычно у него получается хуже, чем самостоятельно написанный SIMD-код. Но зато для применения SIMD уже давно не нужно писать на ассемблере, все делается специальными функциями — интринсиками.

Чаще всего каждому интринсику соответствует одна конкретная инструкция процессора. Т.е. написанный код получается очень эффективный и близкий к железу. Но при этом для написания кода вы пользуетесь знакомым и относительно безопасным синтаксисом Си. Вы как обычно подключаете заголовочный файл, в котором определены функции-интринсики, как обычно объявляете переменные, используя специальные типы данных, и как обычно вызываете функции. Словом, пишите обычный код. Небольшое неудобство только в том, что с SIMD-типами данных нельзя использовать математические операции, для всех вычислений нужно использовать интринсики. Грубо говоря, нельзя написать ss0 + ss1 , можно только add_float(ss0, ss1) (название функции выдумано).

SIMD-расширений много. В основном наличие в процессоре более нового расширения означает наличие всех предшественников. По хронологии появления расширения располагаются в следующем порядке:

MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX-512

Как видите, список внушительный. Не на каждой машине есть каждое расширение. Найти живой x86 процессор без MMX можно разве что в музее. SSE2 — обязательное расширение для 64-битных процессоров, т.е. в наши дни тоже есть практически везде. Поддержку SSE4.2 можно найти в любом процессоре, начиная с архитектуры Nehalem, т.е. с 2008 года. А вот AVX2 есть только у не бюджетных процессоров Intel, начиная с ядра Haswell, т.е. с 2013 года, а у AMD они появились в процессорах Ryzen, выпущенных в 2017 году. AVX-512 пока доступны только в серверных процессорах Intel Xeon и Xeon Phi.

От выбора набора инструкций, зависит производительность и сложность написания кода, а также поддержка процессоров. Иногда разработчики делают несколько реализаций своего кода под разные наборы инструкций. Я выбрал два: SSE4.2 и AVX2. Я рассуждал так: SSE4.2 — базовый набор, который должен быть у всех, кого хоть сколько волнует производительность и не стоит мучаться, реализовывая все, например, на SSE2. А AVX2 для тех, кто не ленится менять железо хотя бы раз в 3 года. Что бы вы не выбрали для своей реализации, со временем ваш выбор будет становиться только более верным, потому что количество процессоров на рынке с выбранным набором инструкций будет только увеличиваться.

SSE4-реализация

Давайте наконец вернемся к коду. Для того, чтобы использовать SSE4.2 в Си, нужно подключить целых три заголовочных файла:

Кроме того, нужно указать флаг компилятора -msse4 . Если речь идет о сборке питоновского модуля (как у нас), то можно добавить этот флаг прямо из командной строки, чтобы не усложнять сейчас сборку:

Наиболее полный справочник по интринсикам можно найти по ссылке Intel Intrinsics Guide. Там есть хороший поиск и фильтрация, в описании интринсиков указаны соответствующие им инструкции, псевдокод инструкций и даже время выполнения в тактах на процессорах Intel последних поколений. Как справочник, это уникальная вещь. Но формат справочника не позволяет составить общую картину, как что должно происходить.

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

Подобный код есть для вертикального и горизонтального прохода. Для удобства вынесем и тот, и другой в отдельные функции и будем использовать SIMD только в рамках двух функций со следующими сигнатурами:

Если вы помните, в предыдущей части я сделал три частных случая для двух, трех и четырех каналов в изображении. Это было нужно, чтобы избавиться от внутреннего цикла по каналам и в то же время не выполнять лишних вычислений для каналов, которых в изображении нет. В SIMD-версии мы не будем делить реализации по каналам: все вычисления всегда будут производиться над четырьмя каналами. Каждый пиксель будет представлен четырьмя 32-битными числами с плавающей точкой и будет занимать ровно один SSE-регистр. Да, для трехканальных изображений четверить операций будет выполняться вхолостую, а для двухканального — половина. Но проще закрыть на это глаза, чем пытаться максимально забить SSE-регистры полезными данными.


Взгляните еще раз на код выше. В самом начале идет присвоение аккумуляторам константного значения 0,5, которое нужно для округления результата. Для загрузки одного float-значения в весь регистр используются функции _mm_set1_* .

Обычно последняя часть названия функции означает тип данных, с которым она работает. В нашем случае это _ps , что означает packed single.

Коэффициент для всех каналов одного пикселя одинаков, так что нам снова пригодится _mm_set1_ps .

Осталось умножить коэффициенты на каналы и сложить с аккумулятором:

Теперь в аккумуляторе sss находится значение каналов пикселя, которые правда могут выходить за диапазон [0, 255], а значит нужно как-то эти значения ограничить. Помните функцию clip8 из предыдущей статьи? В ней было два условных перехода. В случае с SIMD у нас нет возможности использовать условные переходы в зависимости от данных, потому что процессор должен выполнять одну и ту же команду для всех данных. Но на самом деле так даже лучше, потому что есть функции _mm_min_epi32 и _mm_max_epi32 . Поэтому мы переводим значения в целые 32-битные числа со знаком, а потом обрезаем их в пределах [0, 255].

К сожалению, инструкции, обратной _mm_cvtepu8_epi32 , нет, поэтому я не придумал ничего лучше, чем сдвинуть нужные байты в самое начало и потом конвертировать SSE-регистр в регистр общего назначения с помощью _mm_cvtsi128_si32 .

Обратите внимание, в маске shiftmask младшие байты идут справа. Для горизонтального прохода все точно так же, меняется только порядок загрузки пикселей: загружаются соседние пиксели из строки, а не из соседних строк.

Все готово, пришло время запустить тест и узнать результат.

Прирост от двух с половиной до трех раз! Напомню, что тестирую я на трехканальном RGB-изображении, поэтому ускорение в 3 раза в данном случае можно считать эталонным.

Правильная запаковка

Предыдущий вариант был почти 1 в 1 скопирован со скалярного кода. Причем для запаковки и распаковки использовались функции, появившиеся в последних версиях SSE: _mm_cvtepu8_epi32 , _mm_max/min_epi32 , _mm_shuffle_epi8 . Очевидно, что люди как-то справлялись с этими задачами и с более ранними версиями SSE. И действительно, есть целый набор функций по запаковке/распаковке данных, _mm_pack* и _mm_unpack* . И если распаковка тут не сильно помогает ( _mm_cvtepu8_epi32 лучше подходит для наших целей), то запаковку можно сильно упростить. Упростить так, что не понадобятся никакие константы для сдвига и обрезания значений (речь об mmmax , mmmin и shiftmask ).

У меня эта оптимизация не дает ускорения, но зато выглядит красиво и не требует дополнительных констант. Смотреть коммит b17cdc9.

AVX-регистры

Если бы собака носила штаны, делала бы она это так или так?


А если бы регистры содержали в два раза больше данных? Когда я узнал, как работает AVX, то сразу вспомнил об этой картинке. При первом рассмотрении AVX инструкции кажутся странными и нелогичными. Это не просто «как SSE, только в 2 раза больше», в них есть какая-то непонятная логика. Взгляните сами на ту же инструкцию перемешивания, которой мы уже пользовались. Вот псевдокод SSE-версии:

Логично было бы предположить, что для AVX просто должен увеличиться счетчик с 15 до 31. Но нет, псевдокод AVX-версии намного мудренее:

AVX — это не в два раза большее SSE, это два SSE! То есть на AVX-регистры стоит смотреть как на пару векторов. И эти вектора в большинстве команд друг с другом не взаимодействуют. Посмотрите на псевдокод AVX-команды еще раз, там четко видно, что первый блок работает только с младшими 128 битами, а второй только со старшими 128 битами. И нельзя перемешать так, чтобы в старших были младшие байты или наоборот. Причем, для этой инструкции разделение еще не слишком строгое: регистр, который говорит как сдвигать, может по-разному сдвигать верхнюю и нижнюю части. А зачастую бывает, что аргументы операций в обеих частях оказываются одинаковыми. Вот для примера псевдокод _mm256_blend_epi16 :

Обратите внимание, что j итерируется до 15, а маска берется из байта по модулю восьми: imm8[j%8] . Т.е. у верхней и нижней части регистра всегда будет одинаковая маска. Еще много хлопот доставляет распаковка и запаковка, она тоже происходит независимо по верхним и нижним частям.


Нижние биты результата вычисляются только на основе нижних битов входных параметров. А верхние только на основе верхних. Я еще не встречал ни в одном источнике упоминания этого правила в явном виде, но его понимание сильно упрощает портирование SSE-кода на AVX.

AVX-команды

Это значит, что AVX определяет поведение существующих команд с регистрами будущих поколений (512-битными и более). Но это еще не все. Для кодирования AVX-команд применяется система опкодов VEX. AVX включает в себя возможность кодировать в VEX даже SSE-инструкции. Закодированные таким образом SSE-инструкции также получают гарантии обнуления старших битов. Возможно, вы слышали о том, что существует пенальти около сотни тактов за использование AVX-команд после SSE или наоборот. Хорошая новость в том, что это пенальти не распространяется на SSE-команды, закодированные в VEX. И если пользоваться интринсиками, с флагом -mavx компилятор будет генерировать инструкции в новом формате. Плохая новость в том, что если код собран с -mavx и содержит SSE-команды, но не содержит ни одной AVX-команды, он все равно будет закодирован в VEX и не будет работать на процессорах без AVX. Т.е. не получится в рамках одного модуля сборки использовать SSE-инструкции в старом формате и AVX-инструкции:

Потому что с флагом -mavx код из функции resample_sse() не запустится на процессоре без AVX, а без этого флага код из функции resample_avx() даже не скомпилируется.

AVX2, вертикальный проход

До сих пор перевод на SIMD был достаточно простым, потому что в один SSE4-регистр влезает ровно один пиксель, представленный в виде четырех чисел с плавающей точкой. Но с AVX2 мы должны обрабатывать сразу 8 значений с плавающей точкой, то есть два пикселя. Но какие именно пиксели брать в один регистр? Тут мне снова хочется вставить картинку с собакой, которая носит штаны. Напомню, как выглядит каркас, например, горизонтальной свертки:

Можно, например, взять соседние пиксели в строке: lineIn[x] и lineIn[x + 1] , это самый очевидный вариант. Но тогда для этих пикселей придется готовить разные коэффициенты ( k[x - xmin] и k[x - xmin + 1] ). Да и расстояние от xmax до xmin может оказаться нечетным, и чтобы посчитать последний пиксель, нужно будет комбинировать SSE и AVX-код.

Можно взять пиксели в соседних строках: lineIn1[x] и lineIn2[x] . Но тогда загружать и выгружать пиксели придется как-то раздельно, что не очень удобно.

На самом деле любой способ будет иметь какие-то преимущества и недостатки. Скажу прямо, переводить горизонтальный проход на AVX2 не очень-то удобно. Другое дело вертикальный! Посмотрите на него:

Мы можем взять соседние пиксели в строке image32[y][xx] и image32[y][xx + 1] и у них будет одинаковый коэффициент. После выполнения внутреннего цикла в аккумуляторе будет результат для двух соседних пикселей, запаковать его тоже не составит труда. Короче, код можно переписать, просто поменяв все префиксы __m128 на __m256 , а _mm_ на _mm256_ . Единственное, что действительно отличается — использование функций _mm256_castsi256_si128 и _mm_storel_epi64 в конце. Первая — noop, просто приведение типов. А вторая сохраняет 64-битное значение из регистра в память.

Мы впервые получили небольшой проигрыш по производительности. Это не погрешность измерений, т.к. результат достаточно стабилен. Позже я объясню, почему так получилось. А пока видно, что выигрыш есть в основном при увеличении и не сильном уменьшении изображения. Как не трудно догадаться, так происходит потому, что вертикальный проход делается после горизонтального и поэтому оказывает большее влияние при большем размере конечного изображения. В целом же картина достаточно позитивная.

AVX2, горизонтальный проход

Для горизонтального прохода все же оказывается удобнее взять два соседних пикселя в строке. Тогда для них нужно будет подготовить разные коэффициенты:

Ну а в конце результат в верхней части 256-битного регистра нужно будет сложить с результатом в нижней:

Тут мы снова видим для некоторых размеров небольшой проигрыш относительно предыдущего варианта. Но от обоих оптимизаций в сумме мы получили прирост от 6 до 50 процентов. В среднем AVX2-версия быстрее, чем SSE4-версия на 25%.

Много это или мало? Хотелось бы конечно получить от нового набора инструкций намного большего. Понятно, что на прирост в 100% рассчитывать не приходится, хотя бы 50% в среднем было бы тоже неплохо. Но имеем то, что имеем, и смысла отказываться от даже такого ускорения конечно же нет.

Осталось разобраться, почему же мы получали замедление для каждого шага в отдельности в некоторых случаях. Для этого нужно напомнить, на каком компьютере я запускаю тесты. Это обычный ноутбук с потребительским процессором Intel Core i5-4258U. Процессор имеет жесткие рамки по выделяемой мощности, поэтому для него приоритетна не максимальная производительность, а максимальная производительность на выделяемую мощность.

Как вы возможно знаете, последние лет восемь Интел маркирует свои процессоры двумя тактовыми частотами: номинальной и максимальной. Для i5-4258U это 2.4 ГГц и 2.9 ГГц. Со второй понятно — это максимальная частота, которую в принципе может осилить процессор. А первая — это минимальная частота, до которой может опуститься процессор под нагрузкой. Именно под нагрузкой, потому что без нагрузки в целях экономии энергии частота может опускаться гораздо ниже. Есть утилита, которая в реальном времени показывает частоту, температуру и потребление энергии процессором, а еще строит красивые графики. Она называется Intel Power Gadget. Утилита показывает, что во время работы SSE4-версии частота процессора стабильно держится на отметке 2.9 ГГц. При замене вертикального прохода на AVX2-версию, частота начинает скакать возле отметки 2.75 ГГц. А при полном AVX2-ускорении, частота практически не отклоняется от 2.6 ГГц. Т.е. процессор, выполняя AVX2-код, пасует и сбавляет обороты. А так как выигрыш от отдельных AVX2-проходов есть не для любых размеров изображения, мы можем наблюдать падение производительности из-за падения частоты. Однако при полном использовании AVX2 ускорение от более быстрого набора инструкций перекрывает незначительное падение частоты и мы все равно получаем выигрыш. Что тут можно сказать? Не останавливайтесь на полпути, переводите на AVX2 весь код.

Примечательно, что на сервере с процессором Xeon E5-2680 v2 (та же архитектура Haswell, что и в ноутбуке) подобного эффекта не наблюдается — там включение AVX2-проходов не дает падения частоты и, как следствие, не дает проседания производительности.

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

Расширения наборов команд могут включать:

  • Единая Инструкция для множественных данных (SIMD)
  • Процессоры Intel® Streaming SIMD Extensions (Intel® SSE, Intel® SSE2, Intel® SSE3 и Intel® SSE4)
  • Intel® Advanced Vector Extensions (Intel® AVX, Intel® AVX2 и Intel® AVX-512)

Нажмите или в теме, чтобы получить подробную информацию

    .
  • Перейдите на страницу спецификации продукции и введите номер процессоров Intel в поле поиска.
  • На вкладке Advanced Technologies найдите расширения набора команд.

Enter number of the Intel processors


Как узнать, какие расширения набора команд Intel моей системы имеют? Есть ли какое бы то ни было средство, которое отображает эту информацию?

Вы можете использовать программу Intel для идентификации, нажмите на вкладку " технологии ЦП " и найдите расширения набора инструкций Intel®. См. Следующий пример:


Потоковые SIMD-расширения (SSE)

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

SSE предназначен для замены технологии MMX™. Она расширяется по поколениям процессоров Intel®, включая SSE2, SSE3/SSE3S и SSE4. Каждая итерация привела новые инструкции и повышенную производительность.

Потоковые SIMD-расширения 2 (SSE2)

SSE2 расширяет технологии MMX и SSE Благодаря дополнению 144 инструкций, обеспечивающих повышенную производительность для широкого спектра приложений. Инструкции SIMD Integer, представленные с помощью технологии MMX, расширены с 64 на 128 бит. Это удваивает эффективную скорость выполнения операций с типом SIMD Integer.

Удвоенная точность с плавающей запятой позволяет одновременно выполнять две операции с плавающей запятой в формате SIMD. Эта поддержка для операций удвоенной точности помогает ускорить процесс создания контента, составления финансовых, инженерных и научных заявлений.

Первоначальные инструкции SSE усовершенствованы для поддержки гибкого и более высокого динамического диапазона вычислительной мощности. Это делается за счет поддержки арифметических операций над несколькими типами данных. Примерами могут служить двухбайтовые слова и четыре слова. Инструкции SSE2 позволяют разработчикам программного обеспечения обеспечить максимальную гибкость. Они могут реализовывать алгоритмы и обеспечивать повышение производительности при выполнении программного обеспечения, такого как MPEG-2, MP3 и 3D Graphics.

Потоковые SIMD-расширения 3 (SSE3)

В процессоре Intel® Pentium® 4 на базе процессоров Intel-нанометровая тактовая частота представляет собой набор потоковых SIMD-расширений 3 (SSE3), который включает 13 более команд SIMD по сравнению с SSE2.90 13 новых инструкций в основном предназначены для улучшения синхронизации потоков и определенных областей приложения, например для мультимедиа и игр.

Потоковые SIMD-расширения 4 (SSE4)

SSE4 состоит из 54 инструкций. Набор, состоящий из 47 инструкций, который называется SSE 4.1 в документации Intel, доступен в Penryn. SSE 4.2, второй набор, состоящий из семи оставшихся инструкций, впервые доступен в Nehalem-процессоре Intel® Core™ i7. Корпорация Intel имеет обратную информацию от разработчиков при разработке набора инструкций.

Intel® Advanced Vector Extensions (Intel® AVX)

Intel® AVX — это 256-разрядное расширение набора команд Intel® SSE, предназначенное для приложений с интенсивной обработкой плавающих точек (FP). Intel AVX повышает производительность из-за более широкого спектра векторов, нового расширяемого синтаксиса и обширных функциональных возможностей. Intel AVX2 был выпущен в 2013, расширяя возможности обработки векторных изображений в доменах с плавающей запятой и целочисленными данными. Это приводит к более высокой производительности и более эффективному управлению данными в широком диапазоне различных приложений. Примерами могут быть обработка изображений и аудио/видео, инженерные симуляции, финансовая аналитика, 3D-моделирование и анализ.

Intel® Advanced Vector Extensions 512 (Intel® AVX-512)

Intel® AVX-512 позволяет обрабатывать два раза больше элементов данных, которые Intel AVX/AVX2 может обрабатывать с помощью одной инструкции и в четыре раза больше возможностей Intel SSE. Инструкции Intel AVX-512 имеют важное значение, так как они открывают более высокую производительность для самых ресурсоемких вычислительных задач. Инструкции Intel AVX-512 предлагают наивысший уровень поддержки компилятора в конструкции возможностей.

Читайте также: