1 回答
TA貢獻(xiàn)1804條經(jīng)驗(yàn) 獲得超7個(gè)贊
由于沒(méi)有人想做一些拆卸的東西,我回答我自己的問(wèn)題。
原因似乎是 JIT 生成的本機(jī)代碼,而不是注釋中提到的數(shù)組邊界檢查或緩存問(wèn)題。
RyuJIT 為該ClampSimple方法生成了一個(gè)非常有效的代碼:
vucomiss xmm1,xmm0
jbe M01_L00
vmovaps xmm0,xmm1
ret
M01_L00:
vucomiss xmm0,xmm2
jbe M01_L01
vmovaps xmm0,xmm2
ret
M01_L01:
ret
它使用 CPU 的本機(jī)ucomiss操作來(lái)比較floats,并使用快速movaps操作float在 CPU 的寄存器之間移動(dòng)這些s。
擴(kuò)展方法較慢,因?yàn)樗袔讉€(gè)對(duì) 的函數(shù)調(diào)用System.Single.CompareTo(System.Single),這是第一個(gè)分支:
lea rcx,[rsp+30h]
vmovss dword ptr [rsp+38h],xmm1
call mscorlib_ni+0xda98f0
test eax,eax
jge M01_L00
vmovss xmm0,dword ptr [rsp+38h]
add rsp,28h
ret
讓我們看看 Mono 為該ClampSimple方法生成的本機(jī)代碼:
cvtss2sd xmm0,xmm0
movss xmm1,dword ptr [rsp+8]
cvtss2sd xmm1,xmm1
comisd xmm1,xmm0
jbe M01_L00
movss xmm0,dword ptr [rsp+8]
cvtss2sd xmm0,xmm0
cvtsd2ss xmm0,xmm0
jmp M01_L01
M01_L00:
movss xmm0,dword ptr [rsp]
cvtss2sd xmm0,xmm0
movss xmm1,dword ptr [rsp+10h]
cvtss2sd xmm1,xmm1
comisd xmm1,xmm0
jp M01_L02
jae M01_L02
movss xmm0,dword ptr [rsp+10h]
cvtss2sd xmm0,xmm0
cvtsd2ss xmm0,xmm0
jmp M01_L01
M01_L02:
movss xmm0,dword ptr [rsp]
cvtss2sd xmm0,xmm0
cvtsd2ss xmm0,xmm0
M01_L01:
add rsp,18h
ret
Mono 的代碼轉(zhuǎn)換floats為doubles 并使用comisd. 此外,在準(zhǔn)備返回值時(shí),還有奇怪的“轉(zhuǎn)換翻轉(zhuǎn)” float? double? float。而且在內(nèi)存和寄存器之間還有更多的移動(dòng)。這解釋了為什么 Mono 的簡(jiǎn)單方法代碼比 RyuJIT 的代碼慢。
該Extension方法代碼與 RyuJIT 的代碼非常相似,但再次具有奇怪的轉(zhuǎn)換翻轉(zhuǎn)float? double? float:
movss xmm0,dword ptr [rbp-10h]
cvtss2sd xmm0,xmm0
movsd xmm1,xmm0
cvtsd2ss xmm1,xmm1
lea rbp,[rbp]
mov r11,2061520h
call r11
test eax,eax
jge M0_L0
movss xmm0,dword ptr [rbp-10h]
cvtss2sd xmm0,xmm0
cvtsd2ss xmm0,xmm0
ret
似乎 RyuJIT 可以生成更高效的代碼來(lái)處理floats。Mono 將floats 視為doubles 并每次轉(zhuǎn)換值,這也會(huì)導(dǎo)致 CPU 寄存器和內(nèi)存之間的額外值傳輸。
請(qǐng)注意,所有這些僅對(duì) Windows x64 有效。我不知道這個(gè)基準(zhǔn)測(cè)試在 Linux 或 Mac 上的表現(xiàn)如何。
- 1 回答
- 0 關(guān)注
- 353 瀏覽
添加回答
舉報(bào)
