【问题标题】:How to detect AVX2 in Delphi?如何在 Delphi 中检测 AVX2?
【发布时间】:2017-01-04 16:34:38
【问题描述】:

如果 CPU 具有 AVX1 或 AVX2,则以下代码返回 True。有人知道如何修改此代码以准确检测 AVX2 指令支持吗?

function isAvxSupported: Boolean;
asm
{$IFDEF CPUX86}
    push ebx
{$ENDIF}
{$IFDEF CPUX64}
    mov r10, rbx
{$ENDIF}
    xor eax, eax
    cpuid
    cmp eax, 1
    jb @not_supported
    mov eax, 1
    cpuid
    and ecx, 018000000h
    cmp ecx, 018000000h
    jne @not_supported
    xor ecx, ecx
    db 0Fh, 01h, 0D0h //XGETBV
    and eax, 110b
    cmp eax, 110b
    jne @not_supported
    mov eax, 1
    jmp @done
@not_supported:
    xor eax, eax
@done:
{$IFDEF CPUX86}
    pop ebx
{$ENDIF}
{$IFDEF CPUX64}
    mov rbx, r10
{$ENDIF}
end;

【问题讨论】:

标签: delphi


【解决方案1】:

本质上,在使用AVX2之前,你需要检查

  1. 如果通过检查 CPUID 支持 AVX2 指令集。(EAX=07H, ECX=0H):EBX.AVX2[bit 5]=1
  2. 如果操作系统启用了 YMM 寄存器的使用

步骤 1 可以完成,例如使用此功能:


function IsAVX2supported: boolean;
asm
    // Save EBX
    {$IFDEF CPUx86}
      push ebx
    {$ELSE CPUx64}
      mov r10, rbx
    {$ENDIF}
    //Check CPUID.0
    xor eax, eax
    cpuid //modifies EAX,EBX,ECX,EDX
    cmp al, 7 // do we have a CPUID leaf 7 ?
    jge @Leaf7
      xor eax, eax
      jmp @Exit
    @Leaf7:
      //Check CPUID.7
      mov eax, 7h
      xor ecx, ecx
      cpuid
      bt ebx, 5 //AVX2: CPUID.(EAX=07H, ECX=0H):EBX.AVX2[bit 5]=1
      setc al
   @Exit:
   // Restore EBX
   {$IFDEF CPUx86}
     pop ebx
   {$ELSE CPUx64}
     mov rbx, r10
   {$ENDIF}
end;

步骤 2 可以完成,例如使用此功能:


function OSEnabledXmmYmm: boolean;
// necessary to check before using AVX, FMA or AES instructions!
asm
  {$IFDEF CPUx86}
  push ebx
  {$ELSE CPUx64}
  mov r10, rbx
  {$ENDIF}
  mov eax,1
  cpuid
  bt ecx, 27  // CPUID.1:ECX.OSXSAVE[bit 27] = 1 (XGETBV enabled for application use; implies XGETBV is an available instruction also)
  jnc @not_supported
    xor ecx,ecx //Specify control register XCR0 = XFEATURE_ENABLED_MASK register
    db 0Fh, 01h, 0D0h // xgetbv //Reads XCR (extended control register) -> EDX:EAX
    {lgdt eax = db 0Fh, 01h = privileged instruction, so don't go here unless xgetbv is allowed}
      //CHECK XFEATURE_ENABLED_MASK[2:1] = ‘11b’
      and eax, 06h //06h= 00000000000000000000000000000110b
      cmp eax, 06h//; check OS has enabled both XMM (bit 1) and YMM (bit 2) state management support
    jne @not_supported
      mov eax,1
      jmp @out
  @not_supported:
    xor eax,eax
  @out:
 {$IFDEF CPUx86}
  pop ebx
  {$ELSE CPUx64}
  mov rbx, r10
  {$ENDIF}
end;

当然,您也可以使用它来修改您发布的函数,使其只有一个函数可以调用。

【讨论】:

    【解决方案2】:

    好吧我觉得检测AVX2就这么简单

    function isAVX2Supported():boolean;
    var _ebx: Longword;
    begin
    
      asm
        mov eax,7 // EAX=7 -> https://en.wikipedia.org/wiki/CPUID
        db $0F,$A2 // db $0F,$A2 = CPUID instruction
        mov _ebx,ebx
      end;
      if (_ebx and $20) = $20 then isAVX2Supported:=true //Bit 5 = 100000 = $20 (HEX) 
      else isAVX2Supported:=false;
    
    end;
    

    【讨论】:

    • 1) 注意 begin asm end end 不适用于 x64; 2) 并非每个 CPU 都支持 CPUID 上的叶子 7 和 3) 如果您还想 /use/ AVX2,您还必须检查操作系统是否支持/启用它
    • 1) 我使用的是旧的 Delphi 7,所以这不是问题。 2)这是否意味着崩溃? 3) 假设如果检测到的操作系统是 NT6.1 则始终启用 AVX 是否安全?
    • @Atak_Snajpera: 2) 您可能会得到与预期不同的数据。每Intel documentation:“如果为 CPUID.EAX 输入的值高于该处理器的基本或扩展功能的最大输入值,则返回最高基本信息叶的数据 ...如果为 CPUID.EAX 输入的值小于或等于最大输入值并且该处理器不支持叶,则在所有寄存器中返回 0。 "
    • 1) 好吧; 2) 可能不是,但取决于 CPU,结果 可能 未定义(或在某些 CPU 上为零),因此当它不存在时有可能“检测到”AVX2; 3) 我不知道。 Remy 的 cmets 来自 Intel 文档,但您必须咨询所有供应商。
    猜你喜欢
    • 2021-08-05
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多