1. Главная страница » Компьютеры » Avx инструкции в играх

Avx инструкции в играх

Автор: | 16.12.2019

Содержание

Advanced Vector Extensions (AVX) — расширение системы команд x86 для микропроцессоров Intel и AMD, предложенное Intel в марте 2008. [1]

AVX предоставляет различные улучшения, новые инструкции и новую схему кодирования машинных кодов.

Содержание

Улучшения [ править | править код ]

  • Новая схема кодирования инструкций VEX
  • Ширина векторных регистров SIMD увеличивается со 128 (XMM) до 256 бит (регистры YMM0 — YMM15). Существующие 128-битные SSE-инструкции будут использовать младшую половину новых YMM-регистров, не изменяя старшую часть. Для работы с YMM-регистрами добавлены новые 256-битные AVX-инструкции. В будущем возможно расширение векторных регистров SIMD до 512 или 1024 бит. Например, процессоры с архитектурой Xeon Phi уже в 2012 году имели векторные регистры (ZMM) шириной в 512 бит [2] , и используют для работы с ними SIMD-команды с MVEX- и VEX-префиксами, но при этом они не поддерживают AVX. [источник не указан 1421 день]
  • Неразрушающие операции. Набор AVX-инструкций использует трёхоперандный синтаксис. Например, вместо a = a + b <displaystyle a=a+b>можно использовать c = a + b <displaystyle c=a+b>, при этом регистр a <displaystyle a>остаётся неизменённым. В случаях, когда значение a <displaystyle a>используется дальше в вычислениях, это повышает производительность, так как избавляет от необходимости сохранять перед вычислением и восстанавливать после вычисления регистр, содержавший a <displaystyle a>, из другого регистра или памяти.
  • Для большинства новых инструкций отсутствуют требования к выравниванию операндов в памяти. Однако рекомендуется следить за выравниванием на размер операнда, во избежание значительного снижения производительности. [3]
  • Набор инструкций AVX содержит в себе аналоги 128-битных SSE инструкций для вещественных чисел. При этом, в отличие от оригиналов, сохранение 128-битного результата будет обнулять старшую половину YMM регистра. 128-битные AVX-инструкции сохраняют прочие преимущества AVX, такие, как новая схема кодирования, трехоперандный синтаксис и невыровненный доступ к памяти.
  • Intel рекомендует отказаться от старых SSE инструкций в пользу новых 128-битных AVX-инструкций, даже если достаточно двух операндов. [4] .

Новая схема кодирования [ править | править код ]

Новая схема кодирования инструкций VEX использует VEX-префикс. В настоящий момент существуют два VEX-префикса, длиной 2 и 3 байта. Для 2-байтного VEX-префикса первый байт равен 0xC5, для 3-байтного — 0xC4.

В 64-битном режиме первый байт VEX-префикса уникален. В 32-битном режиме возникает конфликт с инструкциями LES и LDS, который разрешается старшим битом второго байта, он имеет значение только в 64-битном режиме, через неподдерживаемые формы инструкций LES и LDS. [3]

Длина существующих AVX-инструкций, вместе с VEX-префиксом, не превышает 11 байт. В следующих версиях ожидается появление более длинных инструкций.

Новые инструкции [ править | править код ]

Инструкция Описание
VBROADCASTSS, VBROADCASTSD, VBROADCASTF128 Копирует 32-, 64- или 128-битный операнд из памяти во все элементы векторного регистра XMM или YMM.
VINSERTF128 Замещает младшую или старшую половину 256-битного регистра YMM значением 128-битного операнда. Другая часть регистра-получателя не изменяется.
VEXTRACTF128 Извлекает младшую или старшую половину 256-битного регистра YMM и копирует в 128-битный операнд-назначение.
VMASKMOVPS, VMASKMOVPD Условно считывает любое количество элементов из векторного операнда из памяти в регистр-получатель, оставляя остальные элементы несчитанными и обнуляя соответствующие им элементы регистра-получателя. Также может условно записывать любое количество элементов из векторного регистра в векторный операнд в памяти, оставляя остальные элементы операнда памяти неизменёнными.
VPERMILPS, VPERMILPD Переставляет 32- или 64-битные элементы вектора согласно операнду-селектору (из памяти или из регистра).
VPERM2F128 Переставляет 4 128-битных элемента двух 256-битных регистров в 256-битный операнд-назначение с использованием непосредственной константы (imm) в качестве селектора.
VZEROALL Обнуляет все YMM-регистры и помечает их как неиспользуемые. Используется при переключении между 128-битным режимом и 256-битным.
VZEROUPPER Обнуляет старшие половины всех регистров YMM. Используется при переключении между 128-битным режимом и 256-битным.

Также в спецификации AVX описана группа инструкций PCLMUL (Parallel Carry-Less Multiplication, Parallel CLMUL)

  • PCLMULLQLQDQ xmmreg, xmmrm [rm: 66 0f 3a 44 /r 00]
  • PCLMULHQLQDQ xmmreg, xmmrm [rm: 66 0f 3a 44 /r 01]
  • PCLMULLQHQDQ xmmreg, xmmrm [rm: 66 0f 3a 44 /r 02]
  • PCLMULHQHQDQ xmmreg, xmmrm [rm: 66 0f 3a 44 /r 03]
  • PCLMULQDQ xmmreg, xmmrm, imm [rmi: 66 0f 3a 44 /r ib]

Применение [ править | править код ]

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

Поддержка [ править | править код ]

Поддержка в операционных системах [ править | править код ]

Использование YMM-регистров требует поддержки со стороны операционной системы. Следующие системы поддерживают регистры YMM:

  • Linux: с версии ядра 2.6.30, [6] released on June 9, 2009. [7]
  • Windows 7: поддержка добавлена в Service Pack 1 [8]
  • Windows Server 2008 R2: поддержка добавлена в Service Pack 1 [8]

Микропроцессоры с AVX [ править | править код ]

  • Intel:
  • Процессоры с микроархитектурой Sandy Br >[9]
  • Процессоры с микроархитектурой Ivy Br >[10]
  • Процессоры с микроархитектурой Piledriver, 2012.
  • Процессоры с микроархитектурой Steamroller, 2014.
  • Процессоры с микроархитектурой Excavator, 2015.
  • Процессоры с микроархитектурой Zen, 2017.
  • Процессоры с микроархитектурой Zen 2, 2019.

Совместимость между реализациями Intel и AMD обсуждается в этой статье.

Микропроцессоры с AVX2 [ править | править код ]

  • IntelHaswell[11]
  • IntelBroadwell
  • IntelSkylake
  • IntelKaby Lake
  • IntelCoffee Lake
  • AMDExcavator
  • AMD Zen (AMD Ryzen)
  • AMD Zen 2 (AMD Ryzen)
Читайте также:  Amd asrock n68c s ucc

AVX-512 [ править | править код ]

AVX-512 расширяет систему команд AVX до векторов длиной 512 бит при помощи кодировки с префиксом EVEX. Расширение AVX-512 вводит 32 векторных регистра (ZMM), каждый по 512 бит, 8 регистров масок, 512-разрядные упакованные форматы для целых и дробных чисел и операции над ними, тонкое управление режимами округления (позволяет переопределить глобальные настройки), операции broadcast (рассылка информации из одного элемента регистра в другие), подавление ошибок в операциях с дробными числами, операции gather/scatter (сборка и рассылка элементов векторного регистра в/из нескольких адресов памяти), быстрые математические операции, компактное кодирование больших смещений. AVX-512 предлагает совместимость с AVX, в том смысле, что программа может использовать инструкции как AVX, так и AVX-512 без снижения производительности. Регистры AVX (YMM0-YMM15) отображаются на младшие части регистров AVX-512 (ZMM0-ZMM15), по аналогии с SSE и AVX регистрами. [12]

Используeтся в Intel Xeon Phi (ранее Intel MIC) Knights Landing (версия AVX3.1) и Intel Skylake-X. [12]

Будущие расширения [ править | править код ]

Схема кодирования инструкций VEX легко допускает дальнейшее расширение набора инструкций AVX. В следующей версии, AVX2, добавлены инструкции для работы с целыми числами, FMA3 (увеличил производительность при обработке чисел с плавающей запятой в 2 раза [11] ), загрузку распределенного в памяти вектора (gather) и прочее.

Различные планируемые дополнения системы команд x86:

В серверных процессорах поколения Broadwell добавлены расширения AVX 3.1, а в серверных процессорах поколения Skylake — AVX 3.2.

k0ttee » 20 сен 2017, 08:27

Сегодня хочу завести разговор на тему, что такое avx инструкции в процессоре, где и для чего они используются.

Среднестатистический покупашка идет в магазин и хочет купить компьютер / ноутбук для работы и для игр. На практике это — помощней и подешевле, чтоб реферат в ворде написать после чего играть.
Что касается процессоров — на полках лежат сердитые пеньки равные по мощности ай-третьим. Неужели i3 это маркетинговый заговор? Неужели Pentium это "такой ай три только дешевле"? И да и нет. А дело вот в чем.

Чтобы написать реферат в ворде — хватит самого дешевого Celeron (причем можно взять "процессор затычку" еще дешевле, если брать его на барахолке с чеком и остатком гарантии).
Чтобы после реферата сыграть во все игры — подойдет Pentium обладающий задатками ай-третьего (2 ядра 4 потока). Для игр AVX-инструкции не обязательны (лишь бы нужные SSE были).

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

Зачем нужны AVX инструкции

Что входит в ряд профессиональных задач? Как правило, лишенные AVX камни так же лишены и аппаратного ускорения виртуализации.
Разработка под android, которая потребует виртуалку этого самого ведроида (некоторые эмуляторы даже не запустятся, некоторые будут работать уныло сильно загружая ядра).
Пережевывание мультимедийных данных (от обработки фоточек до кодирования видео и запиливания трехмерной графики, так что — уже летсплейщикам стоит раскошелиться на процессор подороже).

В процессоре есть регистры для инструкций.
SSE-регистр 128-битный, а AVX-регистр 256-битный.
Таким образом, чтобы не выносить ничей мозг анатомией камня, скажем просто — 256 не влезет в 128.

Без AVX тоже можно обрабатывать фоточки, жевать видео и пилить три-дэ. Но есть нюансы.
Если по-проще, то старый 8-ядерный Xeon (не умеющий AXV) будет пилить видосы с той же скоростью что современный i3 (умеющий AVX).

У процессора есть конвейер: узнал откуда брать из памяти, взял из памяти, вычислил, отправил результаты в память.
Упрощенно конвейер с и без AVX можно изобразить так.

Как видите — операций во втором случае меньше. Из чего логично предположить, что AVX-считалочка работает быстрее (в каждом вычислительном такте). А раз быстрее в каждом такте — тогда имея меньше гигагерц можно вычислять быстрее.

Еще одна вкусность AVX это дополнительный операнд. Используется не 2 операнда а 3, что так же сокращает конвейер. Допустим мы хотим сложить X и Y.
Код: Выделить всё Обычная операция, где 2 операнда (X=X+Y) заставит перезаписывать один из операндов.
AVX операция, где 3 операнда (Z=X+Y) позволяет записать результат в третий операнд.
Сложна? Ок, давайте бум прощэ.

Пилить видосы имея AVX получится быстрее. Ибо, помимо вышеописанного, добавляется плюшка оптимальной разбивки кадров.
Комп пересчитывает не каждый кадр. Он разбивает кадр на прямоугольники и сравнивает их, а если находится подходящий — использует готовый кусочек.
Тут AVX научился работать с видосиками оптимальнее (кому интересно — почитайте у профессионалов, а я ограничусь красивой картинкой).

Раньше разбивка была — как показано слева. AVX-разбивка умеет более умно — как показано справа.

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

Введение

Набор команд AVX

Использование AVX в ассемблерном коде

Определение поддержки AVX системой
Использование AVX-инструкций
Тестирование AVX кода

Чтобы убедиться в работоспособности AVX кода лучше написать к нему Unit-тесты. Однако встаёт вопрос: как запустить эти Unit-тесты, если ни один ныне продаваемый процессор не поддерживает AVX? В этом вам поможет специальная утилита от Intel — Software Development Emulator (SDE). Всё, что умеет SDE — это запускать программы, на лету эмулируя новые наборы инструкций. Разумеется, производительность при этом будет далека от таковой на реальном железе, но проверить корректность работы программы таким образом можно. Использовать SDE проще простого: если у вас есть unit-тест для AVX кода в файле avx-unit-test.exe и его нужно запускать с параметром «Hello, AVX!», то вам просто нужно запустить SDE с параметрами
sde — avx-unit-test.exe "Hello, AVX!"
При запуске программы SDE сэмулирует не только AVX инструкции, но также и инструкции XGETBV и CPUID, так что если вы используете предложенный ранее метод для детектирования поддержки AVX, запущенная под SDE программа решит, что AVX действительно поддерживается. Кроме AVX, SDE (вернее, JIT-компилятор pin, на котором SDE построен) умеет эмулировать SSE3, SSSE3, SSE4.1, SSE4.2, SSE4a, AES-NI, XSAVE, POPCNT и PCLMULQDQ инструкции, так что даже очень старый процессор не помешает вам разрабатывать софт под новые наборы инструкций.

Читайте также:  D link dir 651 a b1a
Оценка производительности AVX кода

Некоторое представление о производительности AVX кода можно получить с помощью другой утилиты от Intel — Intel Architecture Code Analyzer (IACA). IACA позволяет оценить время выполнения линейного участка кода (если встречаются команды условных переходов, IACA считает, что переход не происходит). Чтобы использовать IACA, нужно сначала пометить специальными маркерами участки кода, которые вы хотите проанализировать. Маркеры выглядят следующим образом:
; Начало участка кода, который надо проанализировать
%macro IACA_START 0
mov ebx, 111
db 0x64, 0x67, 0x90
%endmacro

; Конец участка кода, который надо проанализировать
%macro IACA_END 0
mov ebx, 222
db 0x64, 0x67, 0x90
%endmacro
Теперь следует окружить этими макросами тот участок кода, который вы хотите проанализировать
IACA_START
vmovups ymm0, [ecx]
vbroadcastss ymm1, [edx]
vmulps ymm0, ymm0, ymm1
vmovups [ecx], ymm0
vzeroupper
IACA_END
Скомпилированный с этими макросами объектный файл нужно скормить IACA:
iaca -32 -arch AVX -cp DATA_DEPENDENCY -mark 0 -o avx-sample.txt avx-sample.obj
Параметры для IACA нужно понимать так

  • -32 — означает, что входной объектный файл (MS COFF) содержит 32-битный код. Для 64-битного кода нужно указывать -64. Если на вход IACA подаётся не объектный файл (.obj), а исполняемый модуль (.exe или .dll), то этот аргумент можно не указывать.
  • -arch AVX — показывает IACA, что нужно анализировать производительность этого кода на будущем процессоре Intel с поддержкой AVX (т.е. Sandy Bridge). Другие возможные значения: -arch nehalem и -arch westmere.
  • -cp DATA_DEPENDENCY просит IACA показать, какие инструкции находятся на критическом путе для данных (т.е. какие инструкции нужно соптимизировать, чтобы результат работы этого кода вычислялся быстрее). Другое возможное значение: -cp PERFORMANCE просит IACA показать, какие инструкции «затыкают» конвеер процессора.
  • -mark 0 говорит IACA проанализировать все помеченные маркерами участки кода. Если задать -mark n, IACA будет анализировать только n-ый размеченный участок кода.
  • -o avx-sample задаёт имя файла, в который будут записаны результаты анализа. Можно опустить этот параметр, тогда результаты анализа будут выведены в консоль.

Результат запуска IACA приведён ниже:
Intel(R) Architecture Code Analyzer Version — 1.1.3
Analyzed File — avx-sample.obj
Binary Format — 32Bit
Architecture — Intel(R) AVX

Analysis Report
—————
Total Throughput: 2 Cycles; Throughput Bottleneck: FrontEnd, Port2_ALU, Port2_DATA, Port4
Total number of Uops bound to ports: 6
Data Dependency Latency: 14 Cycles; Performance Latency: 15 Cycles

N — port number, DV — Divider pipe (on port 0), D — Data fetch pipe (on ports 2 and 3)
CP — on a critical Data Dependency Path
N — number of cycles port was bound
X — other ports that can be used by this instructions
F — Macro Fusion with the previous instruction occurred
^ — Micro Fusion happened
* — instruction micro-ops not bound to a port
@ — Intel(R) AVX to Intel(R) SSE code switch, dozens of cycles penalty is expected
! — instruction not supported, was not accounted in Analysis

| Num of | Ports pressure in cycles | |
| Uops | 0 — DV | 1 | 2 — D | 3 — D | 4 | 5 | |
————————————————————
| 1 | | | | 1 | 2 | X | X | | | CP | vmovups ymm0, ymmword ptr [ecx]
| 2^ | | | | X | X | 1 | 1 | | 1 | | vbroadcastss ymm1, dword ptr [edx]
| 1 | 1 | | | | | | | | | CP | vmulps ymm0, ymm0, ymm1
| 2^ | | | | 1 | | X | | 2 | | CP | vmovups ymmword ptr [ecx], ymm0
| 0* | | | | | | | | | | | vzeroupper

Самыми важными метриками здесь являются Total Throughput и Data Dependency Latency. Если код, который вы оптимизируете, это небольшая подпрограмма, и в программе есть зависимость по данным от её результата, то вам нужно стараться сделать Data Dependency Latency как можно меньше. В качестве примера может служить приведённый выше листинг подпрограммы vec4_dot_avx. Если же оптимизируемый код — это часть цикла, обрабатывающего большой массив элементов, то ваша задача — уменьшать Total Throughput (вообще-то эта метрика должна была бы называться Reciprocal Throughput, ну да ладно).

Использование AVX в коде на C/C++

Поддержка AVX реализована в следующих популярных компиляторах:

  • Microsoft C/C++ Compiler начиная с версии 16 (входит в Visual Studio 2010)
  • Intel C++ Compiler начиная с версии 11.1
  • GCC начиная с версии 4.4

Для использования 256-битных инструкций AVX в дистрибутив этих компиляторов включен новый заголовочный файл immintrin.h с описанием соответствующих intrinsic-функций. Включение этого заголовочного файла автоматически влечёт за собой включение заголовочных файлов всех SSE-intrinsic’ов. Что касается 128-битных инструкций AVX, то для них нет ни только отдельных хидеров, но и отдельных intrinsics-функций. Вместо этого для них используются intrinsic-функции для SSEx-инструкций, а тип инструкций (SSE или AVX), в которые будут компилироваться вызовы этих intrinsic-функций задаётся в параметрах компилятора. Это означает, что смешать SSE и AVX формы 128-битных инструкций в одном компилируемом файле не получится, и если вы хотите иметь и SSE, и AVX версии функций, то вам придётся писать их в разных компилируемых файлах (и компилировать эти файлы с разными параметрами). Параметры компиляции, которые включают компиляцию SSEx intrinsic-функций в AVX инструкции следующие:

  • /arch:AVX — для Microsoft C/C++ Compiler и Intel C++ Compiler под Windows
  • -mavx — для GCC и Intel C++ Compiler под Linux
  • /QxAVX — для Intel C++ Compiler
  • /QaxAVX — для Intel C++ Compiler

Следует иметь в виду, что данные команды не только изменяют поведение SSEx intrinsic-функций, но и разрешают компилятору генерировать AVX инструкции при компиляции обычного C/C++ кода (/QaxAVX говорит Интеловскому компилятору сгенерировать две версии кода — с AVX инструкциями и с базовыми x86 инструкциями).
Чтобы со всеми этими intrinsic’ами было проще разобраться, Intel сделал интерактивный справочник — Intel Intrinsic Guide, который включает в себя описание всех intrinsic-функций, которые поддерживаются интеловскими процессорами. Для тех инструкций, которые уже реализованы в железе, указаны также latency и throughput. Скачать этот справочник можно с сайта Intel AVX (есть версии для Windows, Linux и Mac OS X).

Читайте также:  Ip68 степень защиты телефона самсунг
Определение поддержки AVX системой

В принципе, для распознавания поддержки AVX системой можно использовать приведённый ранее ассемблерный код, переписав его на inline-ассемблере, либо просто прилинковав собранный ассемблером объектный файл. Однако, если использование inline-ассемблера невозможно (например, из-за coding guidelines, либо потому, что компилятор его не поддерживает, как в случае Microsoft C/C++ Compiler’а для Windows x64), то you are in deep shit. Проблема в том, что intrinsic-функции для инструкции xgetbv не существует! Таким образом, задача разбивается на две части: проверить, что процессор поддерживает AVX (это можно сделать кроссплатформенно) и проверить, что ОС поддерживает AVX (тут уж придётся писать свой код для каждой ОС).
Проверить, что процессор поддерживает AVX можно используя всё ту же инструкцию CPUID, для которой есть intrinsic-функция void __cpuid( int cpuInfo[4], int infoType ). Параметр infoType задаёт значение регистра eax перед вызовом CPUID, а cpuInfo после выполнения функции будет содежать регистры eax, ebx, ecx, edx (именно в таком порядке). Т.о. получаем следующий код:
int isAvxSupportedByCpu() <
int cpuInfo[4];
__cpuid( cpuInfo, 0 );
if( cpuInfo[0] != 0 ) <
__cpuid( cpuInfo, 1 );
return cpuInfo[3] & 0x10000000; // Возвращаем ноль, если 28-ой бит в ecx сброшен
> else <
return 0; // Процессор не поддерживает получение информации о поддерживаемых наборах инструкций
>
>
С поддержкой со стороны ОС сложнее. AVX на сегодня поддерживается следующими ОС:

  • Windows 7
  • Windows Server 2008 R2
  • Linux с ядром 2.6.30 и выше

В Windows была добавлена возможность узнать о поддержке операционкой новых наборов инструкций в виде функции GetEnabledExtendedFeatures из kernel32.dll. К сожалению, эта функция документирована чуть менее, чем никак. Но кое-какую информацию о ней раздобыть всё же можно. Эта функция описана в файле WinBase.h из Platform SDK:
WINBASEAPI
DWORD64
WINAPI
GetEnabledExtendedFeatures(
__in DWORD64 FeatureMask
);
Значения для параметра FeatureMask можно найти в хидере WinNT.h:
//
// Known extended CPU state feature IDs
//

#define XSTATE_LEGACY_FLOATING_POINT 0
#define XSTATE_LEGACY_SSE 1
#define XSTATE_GSSE 2

#define XSTATE_MASK_LEGACY_FLOATING_POINT (1i64

Нетрудно заметить, что маски XSTATE_MASK_* соответствуют аналогичным битам регистра XFEATURE_ENABLED_MASK.
В дополнение к этому, в Windows DDK есть описание функции RtlGetEnabledExtendedFeatures и констант XSTATE_MASK_XXX, как две капли воды похожих на GetEnabledExtendedFeatures и XSTATE_MASK_* из WinNT.h. Т.о. для определения поддержки AVX со стороны Windows можно воспользоваться следующим кодом:
int isAvxSupportedByWindows() <
const DWORD64 avxFeatureMask = XSTATE_MASK_LEGACY_SSE | XSTATE_MASK_GSSE;
return GetEnabledExtendedFeatures( avxFeatureMask ) == avxFeatureMask;
>
Если ваша программа должна работать не только в Windows 7 и Windows 2008 R2, то функцию GetEnabledExtendedFeatures нужно подгружать динамически из kernel32.dll, т.к. в других версиях Windows этой функции нет.

В Linux, насколько мне известно, нет отдельной функции, чтобы узнать о поддержке AVX со стороны ОС. Но вы можете воспользоваться тем фактом, что поддержка AVX было добавлена в ядро 2.6.30. Тогда остаётся только проверить, что версия ядра не меньше этого значения. Узнать версию ядра можно с помощью функции uname.

Использование AVX-инструкций

Написание AVX-кода с использованием intrinsic-функций не вызовет у вас затруднений, если вы когда-либо использовали MMX или SSE посредством intrinsic’ов. Единственное, о чём нужно позаботиться дополнительно, это вызвать функцию _mm256_zeroupper() в конце подпрограммы (как нетрудно догадаться, эта intrinsic-функция генерирует инструкцию vzeroupper). Например, приведённая выше ассемблерная подпрограмма vec4_dot_avx может быть переписана на intrinsic’ах так:
double vec4_dot_avx( double a[4], double b[4] ) <
// mmA = a
const __m256d mmA = _mm256_loadu_pd( a );
// mmB = b
const __m256d mmB = _mm256_loadu_pd( b );
// mmAB = ( a3 * b3, a2 * b2, a1 * b1, a0 * b0 )
const __m256d mmAB = _mm256_mul_pd( mmA, mmB );
// mmABHigh = ( +0.0, +0.0, a3 * b3, a2 * b2 )
const __m256d mmABHigh = _mm256_permute2f128_pd( mmAB, mmAB, 0x81 );
// mmSubSum = ( +0.0, +0.0, a1 * b1 + a3 * b3, a0 * b0 + a2 * b2 )
const __m128d mmSubSum = _mm_add_pd(
_mm256_castpd256_pd128( mmAB ),
_mm256_castpd256_pd128( mmABHigh )
);
// mmSum = ( +0.0, +0.0, +0.0, a0 * b0 + a1 * b1 + a2 * b2 + a3 * b3 )
const __m128d mmSum = _mm_hadd_pd( mmSubSum, _mm_setzero_pd() );
const double result = _mm_cvtsd_f64( mmSum );
_mm256_zeroupper();
return result;
>

Тестирование AVX кода

Если вы используете набор инструкций AVX посредством intrinsic-функций, то, кроме запуска этого кода под эмулятором SDE, у вас есть ещё одна возможность — использовать специальный заголовочный файл, эмулирующий 256-битные AVX intrinsic-функции через intrinsic-функции SSE1-SSE4.2. В этом случае у вас получится исполняемый файл, который можно запустить на процессорах Nehalem и Westmere, что, конечно, быстрее эмулятора. Однако учтите, что таким методом не получиться обнаружить ошибки генерации AVX-кода компилятором (а они вполне могут быть).

Оценка производительности AVX кода

Использование IACA для анализа производительности AVX кода, созданного C/C++ компилятором из intrinsic-функций почти ничем не отличается от анализа ассемблерного кода. В дистрибутиве IACA можно найти заголовочный файл iacaMarks.h, в котором описаны макросы-маркеры IACA_START и IACA_END. Ими нужно пометить анализируемые участки кода. В коде подпрограммы маркер IACA_END должен находиться до оператора return, иначе компилятор «соптимизирует», выкинув код маркера. Макросы IACA_START/IACA_END используют inline-ассемблер, который не поддерживается Microsoft C/C++ Compiler для Windows x64, поэтому если для него нужно использовать специальные варианты макросов — IACA_VC64_START и IACA_VC64_END.

Заключение

В этой статье было продемонстрировано, как разрабатывать программы с использованием набора инструкций AVX. Надеюсь, что это знание поможет вам радовать своих пользователей программами, которые используют возможности компьютера на все сто процентов!

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *