我曾嘗試加速玩具 GEMM 的實作。我處理 32x32 雙打塊,為此我需要一個優化的 MM 內核。我可以訪問 AVX2 和 FMA。
我有下面定義的兩個代碼(在 ASM 中,我為格式的粗略道歉),一個使用 AVX2 功能,另一個使用 FMA。
在不進入微基準測驗的情況下,我想嘗試理解(理論上)為什么 AVX2 實作比 FMA 版本快 1.11 倍。以及可能如何改進這兩個版本。
下面的代碼適用于 3000x3000 MM 的雙打,內核是使用經典的、樸素的 MM 實作的,具有可互換的最深回圈。我使用 Ryzen 3700x/Zen 2 作為開發 CPU。
我沒有嘗試過積極展開,因為擔心 CPU 可能會耗盡物理暫存器。
AVX2 32x32 MM 內核:
Block 82:
imul r12, r15, 0xbb8
mov rax, r11
mov r13d, 0x0
vmovupd ymm0, ymmword ptr [rdi r12*8]
vmovupd ymm1, ymmword ptr [rdi r12*8 0x20]
vmovupd ymm2, ymmword ptr [rdi r12*8 0x40]
vmovupd ymm3, ymmword ptr [rdi r12*8 0x60]
vmovupd ymm4, ymmword ptr [rdi r12*8 0x80]
vmovupd ymm5, ymmword ptr [rdi r12*8 0xa0]
vmovupd ymm6, ymmword ptr [rdi r12*8 0xc0]
vmovupd ymm7, ymmword ptr [rdi r12*8 0xe0]
lea r14, ptr [r12 0x4]
nop dword ptr [rax rax*1], eax
Block 83:
vbroadcastsd ymm8, qword ptr [rcx r13*8]
inc r13
vmulpd ymm10, ymm8, ymmword ptr [rax-0xa0]
vmulpd ymm11, ymm8, ymmword ptr [rax-0x80]
vmulpd ymm9, ymm8, ymmword ptr [rax-0xe0]
vmulpd ymm12, ymm8, ymmword ptr [rax-0xc0]
vaddpd ymm2, ymm10, ymm2
vmulpd ymm10, ymm8, ymmword ptr [rax-0x60]
vaddpd ymm3, ymm11, ymm3
vmulpd ymm11, ymm8, ymmword ptr [rax-0x40]
vaddpd ymm0, ymm9, ymm0
vaddpd ymm1, ymm12, ymm1
vaddpd ymm4, ymm10, ymm4
vmulpd ymm10, ymm8, ymmword ptr [rax-0x20]
vmulpd ymm8, ymm8, ymmword ptr [rax]
vaddpd ymm5, ymm11, ymm5
add rax, 0x5dc0
vaddpd ymm6, ymm10, ymm6
vaddpd ymm7, ymm8, ymm7
cmp r13, 0x20
jnz 0x140004530 <Block 83>
Block 84:
inc r15
add rcx, 0x5dc0
vmovupd ymmword ptr [rdi r12*8], ymm0
vmovupd ymmword ptr [rdi r14*8], ymm1
vmovupd ymmword ptr [rdi r12*8 0x40], ymm2
vmovupd ymmword ptr [rdi r12*8 0x60], ymm3
vmovupd ymmword ptr [rdi r12*8 0x80], ymm4
vmovupd ymmword ptr [rdi r12*8 0xa0], ymm5
vmovupd ymmword ptr [rdi r12*8 0xc0], ymm6
vmovupd ymmword ptr [rdi r12*8 0xe0], ymm7
cmp r15, 0x20
jnz 0x1400044d0 <Block 82>
AVX2/FMA 32x32 MM 內核:
Block 80:
imul r12, r15, 0xbb8
mov rax, r11
mov r13d, 0x0
vmovupd ymm0, ymmword ptr [rdi r12*8]
vmovupd ymm1, ymmword ptr [rdi r12*8 0x20]
vmovupd ymm2, ymmword ptr [rdi r12*8 0x40]
vmovupd ymm3, ymmword ptr [rdi r12*8 0x60]
vmovupd ymm4, ymmword ptr [rdi r12*8 0x80]
vmovupd ymm5, ymmword ptr [rdi r12*8 0xa0]
vmovupd ymm6, ymmword ptr [rdi r12*8 0xc0]
vmovupd ymm7, ymmword ptr [rdi r12*8 0xe0]
lea r14, ptr [r12 0x4]
nop dword ptr [rax rax*1], eax
Block 81:
vbroadcastsd ymm8, qword ptr [rcx r13*8]
inc r13
vfmadd231pd ymm0, ymm8, ymmword ptr [rax-0xe0]
vfmadd231pd ymm1, ymm8, ymmword ptr [rax-0xc0]
vfmadd231pd ymm2, ymm8, ymmword ptr [rax-0xa0]
vfmadd231pd ymm3, ymm8, ymmword ptr [rax-0x80]
vfmadd231pd ymm4, ymm8, ymmword ptr [rax-0x60]
vfmadd231pd ymm5, ymm8, ymmword ptr [rax-0x40]
vfmadd231pd ymm6, ymm8, ymmword ptr [rax-0x20]
vfmadd231pd ymm7, ymm8, ymmword ptr [rax]
add rax, 0x5dc0
cmp r13, 0x20
jnz 0x140004450
Block 82:
inc r15
add rcx, 0x5dc0
vmovupd ymmword ptr [rdi r12*8], ymm0
vmovupd ymmword ptr [rdi r14*8], ymm1
vmovupd ymmword ptr [rdi r12*8 0x40], ymm2
vmovupd ymmword ptr [rdi r12*8 0x60], ymm3
vmovupd ymmword ptr [rdi r12*8 0x80], ymm4
vmovupd ymmword ptr [rdi r12*8 0xa0], ymm5
vmovupd ymmword ptr [rdi r12*8 0xc0], ymm6
vmovupd ymmword ptr [rdi r12*8 0xe0], ymm7
cmp r15, 0x20
jnz 0x1400043f0 <Block 80>
uj5u.com熱心網友回復:
Zen2 有 3 個周期的延遲vaddpd, 5 個周期的延遲vfma...pd。(https://uops.info/)。
您帶有 8 個累加器的代碼具有足夠的 ILP,您預計每個時鐘接近兩個 FMA,每 5 個時鐘大約 8 個(如果沒有其他瓶頸),這比 10/5 理論最大值略低。
vaddpd并且vmulpd實際運行在Zen2上的不同埠上(與 Intel 不同),埠 FP2/3 和 FP0/1 分別,因此理論上可以維持 2/clockvaddpd 和 vmulpd. 由于回圈攜帶依賴的延遲更短,vaddpd如果調度不讓一個 dep 鏈落后,8 個累加器就足以隱藏延遲。(但至少乘法并沒有從中竊取回圈。)
Zen2 的前端是 5 個指令寬(如果有多 uop 指令則為 6 個 uop),它可以將記憶體源指令解碼為單個 uop。所以很可能每次乘以 2/clock 并與非 FMA 版本相加。
如果您可以展開 10 或 12,這可能會隱藏足夠的 FMA 延遲并使其與非 FMA 版本相同,但功耗更低,并且對在另一個邏輯核心上運行的代碼更加 SMT 友好。(10 = 5×2將只是勉強夠,這意味著在其上是關鍵路徑上的DEP鏈的任何調度缺陷失去進展。見為什么mulss只需要3的Haswell周期,從昂納的指令表不同?(開卷FP帶有多個累加器的回圈),以便在 Intel 上進行一些測驗。)
(相比之下,英特爾 Skylake 在相同埠上運行 vaddpd/vmulpd,其延遲與 vfma...pd 相同,均具有 4c 延遲和 0.5c 吞吐量。)
我沒有仔細查看您的代碼,但是 10 個 YMM 向量可能是接觸兩對快取行與接觸 5 條總行之間的權衡,如果空間預取器嘗試完成對齊對,情況可能會更糟。或者可能沒問題。12 個 YMM 向量將是三對,這應該沒問題。
根據矩陣大小,亂序 exec 可能能夠在外回圈的單獨迭代之間重疊內回圈 dep 鏈,特別是如果回圈退出條件可以更快執行并在 FP 作業時解決錯誤預測(如果有)仍在飛行中。對于相同的作業,擁有更少的總 uops 是一個優勢,有利于 FMA。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/392658.html
下一篇:如果column1name==first(value)fromcolumn2BYGROUP,則有條件地從column1取值
