当前位置: 首页 > 知识库问答 >
问题:

xgetbv和CPUID检查是否足以保证AVX2支持?

吕承望
2023-03-14

在这个问题中,确认了< code > _ _ builtin _ CPU _ supports(" av x2 ")不检查操作系统支持。从英特尔文档中,我知道除了检查CPUID位之外,我们还需要检查与x86-64指令< code>xgetbv相关的内容。上面链接的英特尔文档提供了用于检查的代码:

int check_xcr0_ymm()
{
    uint32_t xcr0;
#if defined(_MSC_VER)
    xcr0 = (uint32_t)_xgetbv(0);  /* min VS2010 SP1 compiler is required */
#else
    __asm__ ("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx" );
#endif
    return ((xcr0 & 6) == 6); /* checking if xmm and ymm state are enabled in XCR0 */
}

问题:这个检查加上CPUID检查是否足以保证AVX2指令不会使我的程序崩溃?

额外问题:这张支票到底在做什么?为什么它存在?(这里和这里都有一些讨论,但我认为这个话题值得一个专门的答案)。

注意事项:

  • 这个问题与此主题类似,但答案不包括xgetbv
  • 这个问题类似,但专门询问Windows。我对跨平台解决方案感兴趣

共有1个答案

夏侯俊美
2023-03-14

是的,CPUID检查这些XCR0位就足够了,假设操作系统没有损坏(并遵循预期的约定)。

假设虚拟机或模拟器的CPUID指令没有撒谎,并告诉您AVX2可用,但实际上是错误的。但是,如果发生上述任一情况,则是操作系统或虚拟机的错,而不是程序的错。

(对于使用相当旧的CPU的compat,您需要在使用它之前使用CPUID来检查是否支持XGETBV,否则将会出错。一个好的AVX检测功能将做到这一点。< br >另请参阅哪些版本的Windows支持/需要哪些CPU多媒体扩展?(如何检查上证或AVX是否完全可用?)——我的回答主要集中在后者,并不是Windows特有的。)

如果您只是检查CPUID,您会发现CPU支持AVX2,即使该CPU运行的是不知道AVX的旧操作系统,并且仅在上下文切换上保存/恢复了XMM寄存器,而不是YMM。

Intel设计了这样的东西,在这种情况下,故障模式将是非法指令故障(#UD),而不是在多个线程/进程使用YMM或ZMM寄存器的情况下无声地破坏用户空间状态。(因为那太可怕了。)

(每个任务都应该有自己的私有寄存器状态,包括整数和浮点/SIMD寄存器。如果观察单线程的程序顺序执行,不保存/恢复YMM寄存器的高半部分的上下文切换实际上会异步破坏寄存器。)

其机制是操作系统必须在XCR0(扩展控制寄存器0)中设置一些位,用户空间可以通过< code>xgetbv检查这些位。如果这些位被设置,它实际上是一个promise,即操作系统是AVX意识,并将保存/恢复YMM注册表。并且它将设置其他控制寄存器位,以便SSE和AVX指令实际工作时不会出错。

我不确定这些位是否真的影响了CPU的行为,或者它们是否只是作为一种通信机制存在,用于内核向用户空间宣传AVX支持。

(YMM寄存器是AVX1的新功能,XMM寄存器是SSE1的新功能。OS不需要知道SSE4.x或者AVX2,只需要知道如何保存新的架构状态。因此,AVX-512是下一个需要新操作系统支持的SIMD扩展。)

更新:我认为这些XCR0位实际上控制AVX1/2和AVX-512指令是否将#UD。MacOS的Darwin内核显然只支持按需AVX-512,因此第一次使用会出现故障(但内核会处理它并重新运行,希望对用户空间透明)。见来源:

// darwin-xnu .../i386/fpu.c#L176
 * On-demand AVX512 support
 * ------------------------
 * On machines with AVX512 support, by default, threads are created with
 * AVX512 masked off in XCR0 and an AVX-sized savearea is used. However, AVX512
 * capabilities are advertised in the commpage and via sysctl. If a thread
 * opts to use AVX512 instructions, the first will result in a #UD exception.
 * Faulting AVX512 intructions are recognizable by their unique prefix.
 * This exception results in the thread being promoted to use an AVX512-sized
 * savearea and for the AVX512 bit masks being set in its XCR0. The faulting
 * instruction is re-driven and the thread can proceed to perform AVX512
 * operations.
 *
 * In addition to AVX512 instructions causing promotion, the thread_set_state()
 * primitive with an AVX512 state flavor result in promotion.
 *
 * AVX512 promotion of the first thread in a task causes the default xstate
 * of the task to be promoted so that any subsequently created or subsequently
 * DNA-faulted thread will have AVX512 xstate and it will not need to fault-in
 * a promoted xstate.
 *
 * Two savearea zones are used: the default pool of AVX-sized (832 byte) areas
 * and a second pool of larger AVX512-sized (2688 byte) areas.
 *
 * Note the initial state value is an AVX512 object but that the AVX initial
 * value is a subset of it.
 */

因此,在MacOS上,XGETBV检查XCR0似乎不是检测AVX-512指令可用性的保证方法!评论说“功能在通信页面和通过sysctl进行广告”,因此您需要一些特定于操作系统的方式。

但那是AVX-512;可能AVX1/2总是启用的,所以检查XCR0是否可以在任何地方工作,包括MacOS。

一些操作系统曾经使用“懒惰”上下文切换,实际上并没有保存/恢复x87,XMM,甚至可能是YMM寄存器,直到新进程实际使用它们。这是通过使用单独的控制寄存器位来完成的,如果执行,这些类型的指令就会出错;在该错误处理程序中,操作系统将保存此内核上一个任务的状态,并保存新任务的加载状态。然后更改控制位并返回到用户空间以重新运行指令。

但是现在大多数进程到处都在使用XMM(和YMM)寄存器,在memcpy和其他libc函数中,以及用于复制/初始化结构。所以懒惰的策略是不值得的,而且只是非常复杂,尤其是在SMP系统上。这就是为什么现代内核不再这样做了。

内核用于使x87、xmm或ymm指令发生故障的控制寄存器位与我们正在检查的XCR0位是分开的,因此即使在使用延迟上下文切换的系统上,您的检测也不会被操作系统临时设置的CPU所欺骗,因此vaddps xmm0、xmm1、xmm2会出现故障。

当SSE1是新的时,没有用户空间可见位来检测SSE感知的操作系统,而不使用特定于操作系统的API,但英特尔从AVX的错误中吸取了教训。(但是,对于SSE,故障模式仍然是错误,而不是损坏。CPU 启动时 SSE 指令设置为故障:如何为独立启动代码启用 SSE?

 类似资料:
  • 问题内容: mysql_real_rescape_string()是否足以保护我免受黑客和SQL攻击?问问是因为我听说这些方法不能帮助您抵御所有攻击媒介?寻求专家的建议。 编辑:此外,怎么样的SQL攻击? 问题答案: @查尔斯是非常正确的! 您面临多种 已知 SQL攻击的风险,包括您提到的 SQL注入:是的!Mysql_Escape_String可能仍然使您容易受到SQL注入的影响,具体取决于您在

  • 问题内容: 我特别想知道PostgreSQL。给出以下人为的示例: 从外部查询返回的名称是否保证与内部查询的顺序相同? 问题答案: 不,在外部查询中按以下顺序排序: 内部(子)查询返回结果集。如果按此顺序进行排序,则保证从内部(子)查询传递到外部查询的中间结果集将按照您指定的方式进行排序,但是在外部查询中不对结果进行排序通过处理内部查询结果集生成的结果集,不能保证以任何方式进行排序。

  • 问题内容: 我的应用使用,但是较旧的设备(特别是支持iOS 8的iPad 2和3)不支持模糊处理。 我想检查用户设备是否支持模糊。我该怎么做? 问题答案: 有一种看似有希望的内部方法,但是您的应用程序当然会被Apple拒绝。让我们创建自己的方法: 首先,我们需要知道我们正在使用的确切设备类型: 例如,这将返回iPad 2。这是iDevice型号的更新列表:https : //theiphonewi

  • 问题内容: 有没有办法检查当前是否在电话上注册了URL方案…使用javascript? 问题答案: 不是无缝的。但是,有一种类似于检查弹出窗口是否被阻止的方法。 当您尝试不支持的URL方案时,Safari会警告用户它不知道该怎么做,并停留在同一页面上。 因此,如果您给应用程序调用分配了一些激活时间(例如300毫秒),然后执行其他操作以响应该方案的不存在。 它不是最漂亮,但可以工作:

  • 你好,我正在练习使用C++中的二维数组,我的问题是,例如,如果我想检查4是否有0或11在北,东,南,西作为邻居,它应该返回false。这是我的if 现在我的问题是,由于4的西面和4的北面都超出了界限,它将永远不会返回false。如何优化if条件使其返回false?这是我的二维阵列

  • 问题内容: 如标题所述,我想以编程方式检查域的DNS响应是否受DNSSEC保护。 我该怎么办? 如果有Pythonic解决方案,那就太好了。 更新:更改了响应请求,对于您的困惑感到抱歉 问题答案: 使用DNS解析器(例如),您可以查询域的DNSKEY RRset并打开(dnssec OK)查询标志。如果查询成功,则答案将设置(已认证数据)标志,并将包含区域的RRSIG签名(如果已签名)。 更新:使