Go Wiki:AVX512
Go 1.11 版本推出 AVX-512 支援。
此頁面說明如何使用新功能,以及一些重要的編碼器詳細資料。
術語
大多數術語來自 Intel 軟體開發人員手冊。
後綴源自 Go 組譯器語法,它接近 AT&T,AT&T 也使用大小後綴。
列出一些術語以避免歧義(例如,opcode 可能有不同的含義)。
術語 | 說明 |
---|---|
運算元 | 與「指令參數」相同。 |
opcode |
指指令群組的名稱。例如,VADDPD 是 opcode。它同時指 VEX 和 EVEX 編碼形式以及所有運算元組合。 大多數 AVX-512 的 Go 組譯器 opcode 與 Intel 手冊條目相符,但有例外情況 使用額外大小後綴(例如, VCVTTPD2DQY 是 VCVTTPD2DQ )。
|
opcode 後綴 |
覆寫某些 opcode 屬性的後綴。列在「.」之後(點)。 例如, VADDPD.Z 有「Z」opcode 後綴。可以有多個以點分隔的 opcode 後綴。 |
大小後綴 |
如果無法僅從運算元推斷出指令運算元大小,則指定指令運算元大小的後綴。 例如, VCVTSS2USIL 有「L」大小後綴。
|
opmask |
用於 {k1} 表示法和描述具有 K 暫存器運算元的指令。與 EVEX 前綴中的遮罩支援相關。 |
暫存器區塊 |
編碼暫存器範圍的多來源運算元。 Intel 手冊使用 +n 表示法表示暫存器區塊。例如, +3 是 4 個暫存器的暫存器區塊。
|
FP | 浮點 |
新暫存器
啟用 EVEX 的指令可以存取額外的 16 個 X
(128 位元組 xmm)和 Y
(256 位元組 ymm)暫存器,加上 64 位元模式中的 32 個新 Z
(512 位元組 zmm)暫存器。32 位元模式僅取得 Z0-Z7
。
新的 opmask 暫存器命名為 K0-K7
。
它們可用於遮罩和特殊 opmask 指令(如 KADDB
)。
遮罩支援
支援遮罩的指令可以省略 K
暫存器運算元。
在這種情況下,K0
暫存器是隱含的(「全 1」)且執行合併遮罩。
這實際上是「沒有遮罩」。
K1-K7
暫存器可用於覆寫預設 opmask。
K
暫存器應放置在目的地運算元正前方。
可以使用 Z
opcode 後綴來啟用歸零遮罩。歸零遮罩需要指定 K0 以外的遮罩暫存器。
例如,VADDPD.Z (AX), Z30, K3, Z10
使用歸零遮罩和明確的 K
暫存器。
- 如果移除
Z
opcode 後綴,則會與K3
遮罩執行合併遮罩。 - 如果移除
K3
運算元,則會產生組譯器錯誤。 - 如果移除
Z
opcode 後綴和K3
運算元,則會與K0
遮罩執行合併遮罩。
對於 {k1}
運算元使用 K0
暫存器會產生編譯時期錯誤(有關詳細資訊,請參閱 手冊)。
EVEX 廣播/捨入/SAE 支援
透過 opcode 後綴啟用嵌入式廣播、捨入和 SAE。
對於啟用 {er}
的 reg-reg FP 指令,可以指定捨入 opcode 後綴
RU_SAE
向 +Inf 捨入RD_SAE
向 -Inf 捨入RZ_SAE
向零捨入RN_SAE
向最接近值捨入
如需瞭解更多有關捨入模式的資訊,請參閱 MXCSR.RC 資訊。
對於啟用 {sae}
的 reg-reg FP 指令,可以使用 SAE
opcode 字尾指定例外抑制。
對於具有 m32bcst/m64bcst
參數的 reg-mem 指令,可以使用 BCST
opcode 字尾開啟廣播。
零化 opcode 字尾可以與這些中的任何一個結合使用。
例如,VMAXPD.SAE.Z Z3, Z2, Z1
同時使用 Z
和 SAE
opcode 字尾。
重要的是將零化 opcode 字尾放在最後,否則會出現編譯錯誤。
暫存器區塊(多來源)參數
暫存器區塊使用暫存器範圍語法指定。
僅指定第一個(低)暫存器就足夠了,但 Go 組合器出於可讀性原因需要明確指定兩端的範圍。
例如,具有 +3
範圍的指令可以使用,例如 VP4DPWSSD Z25, [Z0-Z3], (AX)
。
範圍 [Z0-Z3]
讀取為「Z0、Z1、Z2、Z3 的暫存器區塊」。
無效範圍會導致編譯錯誤。
具有 EVEX 前綴的 AVX1 和 AVX2 指令
以前存在的、可以使用 EVEX 前綴編碼的 opcode 現在可以存取 AVX-512 功能,例如更寬的暫存器檔案、零化/合併遮罩等。例如,VADDPD
現在可以使用 512 位元向量暫存器。
請參閱 編碼器詳細資料 以取得更多資訊。
支援的擴充功能
取得支援的擴充功能最新清單的最佳方法是在 測試套件 目錄內執行 ls -1
。
最新清單包括
aes_avx512f
avx512_4fmaps
avx512_4vnniw
avx512_bitalg
avx512_ifma
avx512_vbmi
avx512_vbmi2
avx512_vnni
avx512_vpopcntdq
avx512bw
avx512cd
avx512dq
avx512er
avx512f
avx512pf
gfni_avx512f
vpclmulqdq_avx512f
128 位元和 256 位元指令另外需要 avx512vl
。
也就是說,如果 VADDPD
在 avx512f
中可用,您無法在沒有 avx512vl
的情況下使用 X
和 Y
參數。
檔名遵循 GNU as
(gas) 慣例。
avx512extmap.csv 可以讓命名方案更明顯。
帶有大小字尾的指令
有些操作碼與 Intel 手冊條目不符。
提供此部分以方便搜尋。
Intel 操作碼 | Go 組合器操作碼 |
---|---|
VCVTPD2DQ |
VCVTPD2DQX 、VCVTPD2DQY |
VCVTPD2PS |
VCVTPD2PSX 、VCVTPD2PSY |
VCVTTPD2DQ |
VCVTTPD2DQX 、VCVTTPD2DQY |
VCVTQQ2PS |
VCVTQQ2PSX 、VCVTQQ2PSY |
VCVTUQQ2PS |
VCVTUQQ2PSX 、VCVTUQQ2PSY |
VCVTPD2UDQ |
VCVTPD2UDQX 、VCVTPD2UDQY |
VCVTTPD2UDQ |
VCVTTPD2UDQX 、VCVTTPD2UDQY |
VFPCLASSPD |
VFPCLASSPDX 、VFPCLASSPDY 、VFPCLASSPDZ |
VFPCLASSPS |
VFPCLASSPSX 、VFPCLASSPSY 、VFPCLASSPSZ |
VCVTSD2SI |
VCVTSD2SI 、VCVTSD2SIQ |
VCVTTSD2SI |
VCVTSD2SI 、VCVTSD2SIQ |
VCVTTSS2SI |
VCVTSD2SI 、VCVTSD2SIQ |
VCVTSS2SI |
VCVTSD2SI 、VCVTSD2SIQ |
VCVTSD2USI |
VCVTSD2USIL 、VCVTSD2USIQ |
VCVTSS2USI |
VCVTSS2USIL 、VCVTSS2USIQ |
VCVTTSD2USI |
VCVTTSD2USIL 、VCVTTSD2USIQ |
VCVTTSS2USI |
VCVTTSS2USIL 、VCVTTSS2USIQ |
VCVTUSI2SD |
VCVTUSI2SDL 、VCVTUSI2SDQ |
VCVTUSI2SS |
VCVTUSI2SSL 、VCVTUSI2SSQ |
VCVTSI2SD |
VCVTSI2SDL 、VCVTSI2SDQ |
VCVTSI2SS |
VCVTSI2SSL 、VCVTSI2SSQ |
ANDN |
ANDNL 、ANDNQ |
BEXTR |
BEXTRL 、BEXTRQ |
BLSI |
BLSIL 、BLSIQ |
BLSMSK |
BLSMSKL 、BLSMSKQ |
BLSR |
BLSRL 、BLSRQ |
BZHI |
BZHIL 、BZHIQ |
MULX |
MULXL 、MULXQ |
PDEP |
PDEPL 、PDEPQ |
PEXT |
PEXTL 、PEXTQ |
RORX |
RORXL 、RORXQ |
SARX |
SARXL 、SARXQ |
SHLX |
SHLXL 、SHLXQ |
SHRX |
SHRXL 、SHRXQ |
編碼器詳細資料
由於編碼器表格順序略有不同,因此使用較舊編碼器進行位元比較可能會導致 VEX 編碼指令失敗。
此差異可能會發生在同時具有 {reg, reg/mem}
和 {reg/mem, reg}
形式的指令中,例如 reg-reg 案例。其中一個此類指令為 VMOVUPS
。
這不會影響程式碼行為,也不會讓程式碼變大/效率降低。
新的編碼選擇機制取自 Intel XED。
在下列任何情況下都會使用 EVEX 編碼
- 指令使用新的暫存器(高 16 個
X
/Y
、Z
或K
暫存器) - 指令使用 EVEX 相關的 opcode 後綴,例如
BCST
- 指令使用僅適用於 AVX-512 的運算元組合
在所有其他情況下,都會使用 VEX 編碼。
這表示只要有可能,就會使用 VEX,而只有在需要時才會使用 EVEX。
對於 EVEX 編碼指令,只要有可能,就會套用壓縮 disp8。
這也包含廣播 disp8,它有時具有不同的 N 倍數。
經驗豐富的讀者可以檢查 avx_optabs.go,以瞭解任何指令的 N 倍數。
例如,VADDPD
具有以下倍數
- 512 位元形式的
N=64
;廣播時的N=8
- 256 位元形式的
N=32
;廣播時的N=8
- 128 位元形式的
N=16
;廣播時的N=8
範例
可以在 Go 組譯器 測試套件 中找到大量的範例。
每個檔案都提供特定 AVX-512 延伸指令集的範例。
每個範例也包含產生的機器碼。
以下是採用 Intel® 最佳化手冊 中的「使用 AVX-512CD 的向量化直方圖更新」。
for i := 0; i < 512; i++ {
histo[key[i]] += 1
}
top:
VMOVUPS 0x40(SP)(DX*4), Z4 //; vmovups zmm4, [rsp+rdx*4+0x40]
VPXORD Z1, Z1, Z1 //; vpxord zmm1, zmm1, zmm1
KMOVW K1, K2 //; kmovw k2, k1
VPCONFLICTD Z4, Z2 //; vpconflictd zmm2, zmm4
VPGATHERDD (AX)(Z4*4), K2, Z1 //; vpgatherdd zmm1{k2}, [rax+zmm4*4]
VPTESTMD histo<>(SB), Z2, K0 //; vptestmd k0, zmm2, [rip+0x185c]
KMOVW K0, CX //; kmovw ecx, k0
VPADDD Z0, Z1, Z3 //; vpaddd zmm3, zmm1, zmm0
TESTL CX, CX //; test ecx, ecx
JZ noConflicts //; jz noConflicts
VMOVUPS histo<>(SB), Z1 //; vmovups zmm1, [rip+0x1884]
VPTESTMD histo<>(SB), Z2, K0 //; vptestmd k0, zmm2, [rip+0x18ba]
VPLZCNTD Z2, Z5 //; vplzcntd zmm5, zmm2
XORB BX, BX //; xor bl, bl
KMOVW K0, CX //; kmovw ecx, k0
VPSUBD Z5, Z1, Z1 //; vpsubd zmm1, zmm1, zmm5
VPSUBD Z5, Z1, Z1 //; vpsubd zmm1, zmm1, zmm5
resolveConflicts:
VPBROADCASTD CX, Z5 //; vpbroadcastd zmm5, ecx
KMOVW CX, K2 //; kmovw k2, ecx
VPERMD Z3, Z1, K2, Z3 //; vpermd zmm3{k2}, zmm1, zmm3
VPADDD Z0, Z3, K2, Z3 //; vpaddd zmm3{k2}, zmm3, zmm0
VPTESTMD Z2, Z5, K2, K0 //; vptestmd k0{k2}, zmm5, zmm2
KMOVW K0, SI //; kmovw esi, k0
ANDL SI, CX //; and ecx, esi
JZ noConflicts //; jz noConflicts
ADDB $1, BX //; add bl, 0x1
CMPB BX, $16 //; cmp bl, 0x10
JB resolveConflicts //; jb resolveConflicts
noConflicts:
KMOVW K1, K2 //; kmovw k2, k1
VPSCATTERDD Z3, K2, (AX)(Z4*4) //; vpscatterdd [rax+zmm4*4]{k2}, zmm3
ADDL $16, DX //; add edx, 0x10
CMPL DX, $1024 //; cmp edx, 0x400
JB top //; jb top
此內容是 Go Wiki 的一部分。