出于测试目的在 CPU 中禁用 AVX2

Disabling AVX2 in CPU for testing purposes

我有一个应用程序需要 AVX2 才能正常工作。实施检查以检查 CPU 是否有 AVX2 指令。我想检查它是否正常工作,但我只有 CPU 有 AVX2。有没有办法暂时将其关闭以进行测试?或者以某种方式模仿其他 CPU?

是的,使用 "emulation"(或动态重新编译)层,如 Intel's Software Development Emulator (SDE),或者 QEMU。

SDE 是闭源免费软件,对于在旧 CPU 上测试 AVX512 代码或 模拟 旧 CPU 上的 AVX512 代码都非常方便检查你是否不小心执行了太新的指令。

示例:我碰巧有一个二进制文件无条件地使用 AVX2 vpmovzxwq 加载指令(针对我正在测试的功能)。它 运行 在我的 Skylake CPU 上本身很好,但 SDE 有一个 -snb 选项可以在 CPUID 中模拟 Sandybridge 并实际检查每条指令。

 $ 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) 到新的 CPU IceLake-Server (-icx) 或 Tremont (-tnt)。 (Xeon Phi CPU 类似于 KNL 和 KNM。)

它 运行 非常快,使用动态重新编译 (JIT),因此仅使用 本机支持的指令的代码可以 运行 基本上以本机速度,我觉得。

它还有检测选项(如 -mix 转储指令组合)和更紧密地控制 JIT 的选项。我想你可以让它不在 CPUID 中报告 AVX2,但仍然让 AVX2 指令 运行 没有错误。

或者可能模拟支持 AVX2 但 不支持 FMA 的 CPU(不幸的是,Via 有一个像这样的真实 CPU)。或者真正的 CPU 没有的组合,比如 AVX2 但 popcnt 没有,或者 BMI1/BMI2 但 AVX 没有。但我还没有研究如何做到这一点。

基本 sde -help 选项仅允许您将其设置为特定的 Intel CPUs,并用于检查可能较慢的 SSE/AVX转换(没有正确的 vzeroupper 用法)。还有一些其他的事情。

SDE 缺少的一个重要测试用例是 AVX+FMA 没有 AVX2(AMD Piledriver / Steamroller,即大多数 AMD FX 系列 CPUs). 很容易忘记并在本应是 AVX1+FMA3 的代码中使用 AVX2 shuffle,并且某些编译器(如 MSVC)不会在编译时以这种方式捕捉到这一点 gcc -march=bdver2 将。 (Bulldozer 只有 AVX + FMA4,没有 FMA3,因为英特尔改变了他们的计划,AMD 来不及重新设计。)


如果您只是希望 CPUID 不报告 AVX2(和 FMA?)的存在,以便您的代码使用其 AVX1 或非 AVX 版本的函数,您可以在大多数 VM 上做到这一点。

对于 运行 的 AVX 指令没有错误,必须设置控制寄存器中的一位。 (所以这就像 OS 的承诺一样,它将正确 save/restore YMM 上半部分的新架构状态)。因此,在 CPUID 中禁用 AVX 将为您提供一个 AVX 指令出错的 VM 实例。 (至少是 256 位指令?我还没有尝试查看 128 位 AVX 指令是否仍然可以在支持 AVX 的硬件上以这种状态执行。)