java启动参数xmm_更快的方法来测试xmm / ymm寄存器是否为零?
實際上,現有方法不是“非常慢”,而是合理的 .
當然每個單獨的測試都有4個周期的延遲1,但是如果你想將結果放在通用寄存器中,你通常會為這個移動支付3個周期的延遲(例如, movmskb 也有3個延遲) . 在任何情況下,您都想測試8個寄存器,而不是簡單地添加延遲,因為每個寄存器大多是獨立的,因此uop計數和端口使用可能最終會使測試單個寄存器的延遲變得更加重要延遲與其他工作重疊 .
在英特爾硬件上可能更快一點的方法是使用連續的 PCMPEQ 指令,測試幾個向量,然后將結果折疊在一起(例如,如果你使用PCMPEQQ,你實際上有4個四字結果,需要折疊它們進入1) . 您可以在 PCMPEQ 之前或之后折疊,但這將有助于更多地了解您希望結果如何/在哪里提出更好的結果 . 這是一個未經測試的8個寄存器草圖,其中 xmm1-8 假設為零,而 xmm14 是 xmm14 掩碼,用于選擇最后一條指令中使用的備用字節 .
# test the 2 qwords in each vector against zero
vpcmpeqq xmm11, xmm1, xmm0
vpcmpeqq xmm12, xmm3, xmm0
vpcmpeqq xmm13, xmm5, xmm0
vpcmpeqq xmm14, xmm7, xmm0
# blend the results down into xmm10 word origin
vpblendw xmm10, xmm11, xmm12, 0xAA # 3131 3131
vpblendw xmm13, xmm13, xmm14, 0xAA # 7575 7575
vpblendw xmm10, xmm10, xmm13, 0xCC # 7531 7531
# test the 2 qwords in each vector against zero
vpcmpeqq xmm11, xmm2, xmm0
vpcmpeqq xmm12, xmm4, xmm0
vpcmpeqq xmm13, xmm6, xmm0
vpcmpeqq xmm14, xmm8, xmm0
# blend the results down into xmm11 word origin
vpblendw xmm11, xmm11, xmm12, 0xAA # 4242 4242
vpblendw xmm13, xmm13, xmm14, 0xAA # 8686 8686
vpblendw xmm11, xmm11, xmm13, 0xCC # 8642 8642
# blend xmm10 and xmm11 together int xmm100, byte-wise
# origin bytes
# xmm10 77553311 77553311
# xmm11 88664422 88664422
# res 87654321 87654321
vpblendvb xmm10, xmm10, xmm11, xmm15
# move the mask bits into eax
vpmovmskb eax, xmm10
and al, ah
直覺是你在每個 xmm 中測試每個 QWORD 對零,為8個寄存器提供16個結果,然后將結果混合到 xmm10 中,每個字節按順序結束一次結果(所有高QWORD結果在所有之前)低QWORD結果) . 然后將這些16字節掩碼作為16位移動到帶有 movmskb 的 eax 中,最后將 eax 中的每個寄存器的高位和低位 QWORD 位組合起來 .
對于8個寄存器來說,這對我來說總共有16個uop,所以每個寄存器大約有2個uop . 總延遲是合理的,因為它主要是"reduce"類型的并行樹 . 一個限制因素是6 vpblendw 操作,這些操作都僅限于現代英特爾的端口5 . 最好用 VPBLENDD 替換其中的4個,這是_2904699_的任何一個"blessed"混合 . 這應該是直截了當的 .
所有操作都簡單快捷 . 最終的 and al, ah 是一個部分寄存器寫入,但是如果你 mov 之后進入 eax 也許沒有懲罰 . 如果這是一個問題,你也可以通過幾種不同的方式完成最后一行......
這種方法也可以自然地擴展到 ymm 寄存器,最后在 eax 中折疊略有不同 .
EDIT
稍微快一點的結尾使用打包移位來避免兩個昂貴的指令:
;combine bytes of xmm10 and xmm11 together into xmm10, byte wise
; xmm10 77553311 77553311
; xmm11 88664422 88664422 before shift
; xmm10 07050301 07050301
; xmm11 80604020 80604020 after shift
;result 87654321 87654321 combined
vpsrlw xmm10,xmm10,8
vpsllw xmm11,xmm11,8
vpor xmm10,xmm10,xmm11
;combine the low and high dqword to make sure both are zero.
vpsrldq xmm12,xmm10,64
vpand xmm10,xmm12
vpmovmskb eax,xmm10
通過避免2周期 vpblendvb 和 or al,ah 的部分寫入懲罰,這節省了2個周期,如果不需要立即使用該指令的結果,它還修復了對慢 vpmovmskb 的依賴性 .
事實上,似乎只有在Skylake上 PTEST 有三個周期的延遲,之前它似乎是2.我也不確定你為 rcl eax, 1 列出的1個周期延遲:根據Agner,它似乎是3現代英特爾的uops和2個周期延遲/接收器吞吐量 .
總結
以上是生活随笔為你收集整理的java启动参数xmm_更快的方法来测试xmm / ymm寄存器是否为零?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 卓有成效的管理:你逃不过的功课你要完成它
- 下一篇: XMM SSE2浮点指令