為啥JVM等虛擬機都沒考慮實現自動矢量化處理?

現在主流虛擬機包括jvm,.net都沒有實現自動矢量化循環以利用CPU的SIMD指令集,在gcc下可以通過打開-ftree-vectorize開關啟用特定循環代碼的矢量化,利用SSE或NEON指令集將循環性能提升50%甚至更多,為什麼現在SIMD指令集已經成為幾乎所有處理器的標準配置,jvm等這類號稱能夠實時編譯將代碼針對硬體和環境進行優化的JIT虛擬機卻不能通過利用CPU的DSP指令集直接對位元組碼性能進行提升,而逼得開發人員不得不使用jni等手段以充分利用處理器的計算性能。


先問是不是再問為什麼系列?

題主要是跑Java的話,可以試試找些benchmark跑跑看,對比默認參數的情況和使用-XX:-UseSuperWord的情況,後者會關掉SuperWord優化(自動向量化的一種演算法),看看有多少差異。

從JDK6開始的HotSpot VM所使用的自動向量化演算法就叫superword,是一種非常簡單、有一點點效果的做法。這個演算法來自PLDI 2000的一篇論文,Exploiting Superword Level Parallelism with Multimedia Instruction Sets。具體來說,HotSpot VM的Server Compiler(C2)所實現的是這篇論文里所說的功能的一個子集,只對循環做superword優化。

相關實現的代碼在這裡:jdk9/jdk9/hotspot: 252987f4f36a src/share/vm/opto/superword.hpp

這玩兒在HotSpot里也有大概10年左右的歷史了吧…

實際對循環代碼的效果,請看我的一篇老博文提到的例子:降序循環總是比升序循環快?

另外Intel有篇老文也印證過HotSpot VM有做向量化,Identifying JVM Vectorization (SIMD) Usage with the VTune? Performance Analyzer,隨便參考下。

像GCC、LLVM有更強力的自動向量化演算法,末尾也會跑一下superword來捕捉一些遺漏的情況,增強自動向量化的效果。

除了superword之外,HotSpot VM還對不少熱點方法做了專項優化,所謂intrinsics。例如說CRC32(非CRC32C)和一些String方法的intrinsic實現是手寫的SIMD指令實現的。這樣也可以幫助Java應用搭上CPU新指令的車。

=====================================

IBM J9 JVM顯然也不會錯過SIMD這麼大的feature。J9的Testarossa JIT編譯器里也有實現自動向量化優化,可以使用上SIMD功能的。不過J9 VM尚未開源(就快開源了!),所以外界還不知道它具體用了哪些自動向量化演算法。

隨便放個傳送門:Java Performance on IBM z Systems: IBM z13 and IBM Java SDK 8

=====================================

另外,關於.NET:雖然CLR沒有花大力氣做自動向量化優化,但.NET 4.6開始暴露出來的新SIMD API可以讓程序員可控地使用SIMD功能。請跳傳送門:

  • SIMD + C# = Parallelism on a Single Core

  • The JIT finally proposed. JIT and SIMD are getting married.

  • RyuJIT CTP3: How to use SIMD

  • RyuJIT CTP5: Getting closer to shipping, and with better SIMD support


瞎扯兩句 即使在GCC LLVM上也是很費勁但效果一般的優化

一方面是由於C的指針 需要做很費時的別名分析

另一方面 問題本身很複雜:外層循環怎麼做向量化;就算是單循環,裡面有控制流改怎麼辦,有循環依賴怎麼辦 依賴的距離多少?都要計算,很不簡單

比如哪怕對一個數組求和,也不那麼簡單


推薦閱讀:

.NET/CLR都開源了,VC++還遠嗎?
CLR 相比 JVM有哪些先進之處?
.NET CLR怎麼保證執行正確的unsafe代碼不掛掉?
C#里的顯式介面實現是什麼原理?
如何開始學習CoreCLR源代碼?

TAG:Java虛擬機JVM | 即時編譯JIT | 編譯原理 | CLR |