Да, используйте слой «эмуляции» (или динамической перекомпиляции), например Эмулятор разработки программного обеспечения Intel (SDE) или, возможно, QEMU.
SDE - бесплатная программа с закрытым исходным кодом, которая очень удобна как для тестирования кода AVX512 на старых процессорах, так и для имитации старых процессоров, чтобы убедиться, что вы случайно не выполняете слишком новые инструкции.
Пример: у меня получился двоичный файл, который безоговорочно использует инструкцию загрузки AVX2 vpmovzxwq
(для функции, которую я тестировал). Он нормально работает на моем процессоре Skylake, но SDE имеет опцию -snb
, чтобы эмулировать Sandybridge в обоих CPUID и фактически проверять каждую инструкцию.
$ sde64 -snb -- ./mask
TID 0 SDE-ERROR: Executed instruction not valid for specified chip (SANDYBRIDGE): 0x401005: vpmovzxwq ymm2, qword ptr [rip+0xff2]
Image: /tmp/mask+0x5 (in multi-region image, region# 1)
Instruction bytes are: c4 e2 7d 34 15 f2 0f 00 00
Существуют опции для эмуляции процессоров таких же старых, как -quark
, -p4
(SSE2) или Core 2 Merom (-mrm
), до новых, таких как IceLake-Server (-icx
) или Tremont (* 1018) *). (И процессоры Xeon Phi, такие как KNL и KNM.)
Он работает довольно быстро, с использованием динамической перекомпиляции (JIT), поэтому код, использующий только инструкции, которые поддерживаются изначально поддерживается, может работать в основном на собственной скорости, я думаю.
Он также имеет опции инструментария (например, -mix
для вывода набора команд) и опции для более точного управления JIT. Я думаю, что вы могли бы заставить его не сообщать AVX2 в CPUID, но все же позволить инструкциям AVX2 работать без сбоев.
Или, возможно, эмулировать процессор, который поддерживает AVX2, но , а не FMA (к сожалению, существует настоящий процессор от Via). Или комбинации, которых нет у реального процессора, например AVX2, но не popcnt
, или BMI1 / BMI2, но не AVX. Но я не изучал, как это сделать.
Базовые опции sde -help
позволяют устанавливать только определенные Intel ЦП и проверять потенциально медленные переходы SSE / AVX (без правильного использования vzeroupper). И еще несколько вещей.
Одним из важных тестовых примеров, в котором отсутствует SDE, является AVX + FMA без AVX2 (AMD Piledriver / Steamroller, то есть большинство процессоров AMD FX-series). Это легко забыть и используйте перемешивание AVX2 в коде, который должен быть AVX1 + FMA3, и некоторые компиляторы (например, MSVC) не поймут это во время компиляции, как gcc -march=bdver2
. (У Bulldozer есть только AVX + FMA4, а не FMA3, потому что Intel изменила свои планы после того, как AMD слишком поздно сменила дизайн.)
Если вы просто хотите, чтобы CPUID не сообщал о наличии AVX2 (и FMA?), Поэтому ваш код использует его версии функций AVX1 или не-AVX, вы можете сделать это с большинством виртуальных машин.
Чтобы команды AVX выполнялись без ошибок, в регистре управления должен быть установлен бит. (Таким образом, это работает как обещание ОС, что она будет правильно сохранять / восстанавливать новое архитектурное состояние верхних половин YMM). Таким образом, отключение AVX в CPUID даст вам экземпляр виртуальной машины, где ошибка инструкций AVX. (По крайней мере, 256-битные инструкции? Я не пробовал это проверить, могут ли 128-битные инструкции AVX все еще выполняться в этом состоянии на HW, который поддерживает AVX.)