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

Posted

技术标签:

【中文标题】出于测试目的在 CPU 中禁用 AVX2【英文标题】:Disabling AVX2 in CPU for testing purposes 【发布时间】:2019-04-19 13:07:08 【问题描述】:

我有一个需要 AVX2 才能正常工作的应用程序。如果 CPU 有 AVX2 指令,则在应用程序启动期间执行检查以检查。我想检查它是否正常工作,但我只有具有 AVX2 的 CPU。有没有办法暂时关闭它以进行测试?或者以某种方式模拟其他 CPU?

【问题讨论】:

如果 Peter 的解决方案对您不起作用,某些 Bios 也允许您禁用 AVX2。 【参考方案1】:

是的,使用“模拟”(或动态重新编译)层,例如 Intel's Software Development Emulator (SDE),或者可能是 QEMU。

SDE 是封闭源代码的免费软件,非常方便在旧 CPU 上测试 AVX512 代码,或模拟旧 CPU 以检查您不会意外执行太新的指令。

示例:我碰巧有一个二进制文件,它无条件地使用 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 (@987654329) 这样新的 CPU @)。 (以及 KNL 和 KNM 等 Xeon Phi CPU。)

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

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

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

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

SDE 缺少的一个重要测试用例是 AVX+FMA 没有 AVX2(AMD Piledriver / Steamroller,即大多数 AMD FX 系列 CPU)。忘记并在应该是 AVX1+FMA3 的代码中使用 AVX2 shuffle,并且某些编译器(如 MSVC)不会像 gcc -march=bdver2 那样在编译时捕捉到这一点。 (Bulldozer 只有 AVX + FMA4,没有 FMA3,因为 Intel 在 AMD 重新设计为时已晚后改变了计划。)


如果您只是希望 CPUID 不报告 AVX2(和 FMA?)的存在,以便您的代码使用其 AVX1 或非 AVX 版本的函数,您可以对大多数 VM 执行此操作。

要使 AVX 指令正常运行,必须设置控制寄存器中的位。 (所以这就像操作系统承诺的那样,它将正确保存/恢复 YMM 上半部分的新架构状态)。因此,在 CPUID 中禁用 AVX 将为您提供一个 AVX 指令出错的 VM 实例。 (至少 256 位指令?我没有试过这个,看看 128 位 AVX 指令是否仍然可以在支持 AVX 的硬件上以这种状态执行。)

【讨论】:

以上是关于出于测试目的在 CPU 中禁用 AVX2的主要内容,如果未能解决你的问题,请参考以下文章

禁用 CloudKit 调试日志

禁用 IntelliJ CPU 分析器

在我的网站上禁用 Chrome 翻译栏

暂时禁用Java图形小程序中的双缓冲

运行单元测试时禁用winston日志记录?

出于安全原因,已禁用消息“mail() 引发的 ErrorException