Здесь есть несколько частей для ответа.
Во-первых, классический 32-битный код Intel x86 использовал набор команд x87 для плавающей запятой, и компилятор генерировал код, используяfloat
и double
типы для x87.Долгое время это было поведение по умолчанию для компилятора Visual C ++ при сборке для 32-битной системы.Вы можете принудительно использовать его с 32-разрядным кодом с помощью /arch:IA32
- этот параметр недопустим для 64-разрядных.
Для 64-разрядных кодов AMD64 (который также был принят Intel для 64-разрядныхизвестный как x64), набор команд x87 устарел вместе с 3DNow!и инструкции Intel MMX при работе в 64-битном режиме.Вместо этого весь код типа float
и double
генерируется с использованием SSE / SSE2, хотя необязательно с использованием полных 4-х чисел с плавающей запятой или двух двойных элементов из регистров XMM
.Вместо этого компилятор обычно генерирует скалярные версии инструкций SSE / SSE2, которые используют только XMML
- и на самом деле __fastcall
соглашение о вызовах и правила маршаллинга .NET для 64-битных систем имеют дело только с XMML
.Это поведение по умолчанию для компилятора Visual C ++ при сборке для 64-битной системы.Вы также можете использовать тот же кодовый код для 32-разрядных систем с помощью переключателей /arch:SSE
или /arch:SSE2
- эти переключатели недопустимы для x64, поскольку они уже должны быть там.
Начиная сVisual C ++ 2015, /arch:SSE2
является значением по умолчанию для 32-разрядного кода gen и неявно требуется для всего 64-разрядного кода gen.
Это приводит нас к /arch::AVX
.Как для 32-битного, так и для 64-битного кодгена, это позволяет компилятору использовать префикс VEX для кодирования инструкций SSE / SSE2 (либо генерируемых математическим компилятором, о котором я говорил выше, либо через явное использование встроенных функций компилятора).Эта кодировка использует 3-операнд (dest, src1, src2)
вместо традиционного 2-операнда (dest/src1, src2)
для кода Intel.Конечным результатом этого является то, что весь кодекс SSE / SSE2 более эффективно использует доступные регистры.Это действительно большая часть того, что дает вам использование /arch:AVX
.
Существуют и другие аспекты компилятора, которые также используют настройки переключателя /arch
, такие как оптимизированный memcpy
и набор команд, которыйдоступны для использования автоматическим векторизатором в сборках /O2
и /Ox
и т. д. Компилятор также предполагает, что если вы используете /arch:AVX
, он может свободно использовать SSE3, SSSE3, SSE4.1, SSE4.2 или AVXинструкции, а также SSE / SSE2.
С /arch:AVX2
вы получаете то же поведение с префиксом VEX и наборами инструкций, плюс компилятор может выбрать оптимизацию кода для использования слияния-умножения (FMA3)инструкция, которая требуется для AVX2.Авто-векторизатор также может использовать инструкции AVX2 с активным этим переключателем.
TL; DR: Если вы используете встроенные функции компилятора, вы берете на себя ответственность за то, чтобы они не потерпели крах привремя выполнения из-за недопустимого исключения инструкции.Переключатель /arch
просто позволяет вам указать компилятору использовать расширенные наборы команд и кодирование везде.
См. Эту серию блогов для получения дополнительной информации: DirectXMath: SSE, SSE2 иARM-NEON ; SSE3 и SSSE3 ; SSE4.1 и SSE 4.2 ; AVX ; F16C и FMA ;и AVX2