#include <immintrin.h>
__m256 mult(__m256 num) {
return 278*num/(num 1400);
}
.LCPI0_0:
.long 0x438b0000 # float 278
.LCPI0_1:
.long 0x44af0000 # float 1400
mult(float __vector(8)): # @mult(float __vector(8))
vbroadcastss ymm1, dword ptr [rip .LCPI0_0] # ymm1 = [2.78E 2,2.78E 2,2.78E 2,2.78E 2,2.78E 2,2.78E 2,2.78E 2,2.78E 2]
vmulps ymm1, ymm0, ymm1
vbroadcastss ymm2, dword ptr [rip .LCPI0_1] # ymm2 = [1.4E 3,1.4E 3,1.4E 3,1.4E 3,1.4E 3,1.4E 3,1.4E 3,1.4E 3]
vaddps ymm0, ymm0, ymm2
vrcpps ymm2, ymm0
vmulps ymm3, ymm1, ymm2
vfmsub213ps ymm0, ymm3, ymm1 # ymm0 = (ymm3 * ymm0) - ymm1
vfnmadd213ps ymm0, ymm2, ymm3 # ymm0 = -(ymm2 * ymm0) ymm3
ret
為什么 Clang 會在代碼中添加兩個額外的 FMA 指令?結果應該已經計算出來了vmulps ymm3, ymm1, ymm2。vdivps除了使用like with之外,額外的指令不會增加延遲-O3嗎?
神螺栓
uj5u.com熱心網友回復:
額外的 FMA 補償了vrcpps. ymm3是對結果的估計,但大約是通常精度的一半。
為簡單起見,假設除法是q = a / b。
第一個 FMAvfmsub213ps計算差異(a * b?1) * b - a,這是對除以“關閉”多少(在原始比例中,在除以之前b)的估計。第二個 FMA 大約將該差異除以b(通過乘以b?1),因此它成為 的比例差異q,并將其減去q以使其更接近a / b。
如果您可以降低精度,您可以明確使用_mm256_rcp_ps并乘以它,那么將不會有額外的 FMA 來補償。
不要額外的指令增加延遲不僅僅是使用
vdivps
是的,這個 4 條指令序列在 Ice Lake 上需要 16 個回圈,而在 Ice Lake 上vdivps需要 11 個回圈。但是,與 相比,吞吐量大約翻了一番vdivps。根據背景關系,延遲或吞吐量可能更重要..更常見的是吞吐量。編譯器不一定非常擅長決定哪個更重要,盡管在這種情況下我不能責怪它(沒有背景關系)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/495527.html
下一篇:c 如何在執行緒終止后洗掉執行緒
