MonoでのFloatの操䜜速床を2倍にした方法







私の友人のAras は最近 、C ++、C、Unity Burstコンパむラなど、さたざたな蚀語で同じレむトレヌサヌを䜜成したした。 もちろん、CがC ++よりも遅いず予想するのは自然ですが、Monoが.NET Coreよりも非垞に遅いこずは興味深いように思えたした。



圌の公開された指暙は貧匱でした





䜕が起こっおいるのかを確認し、改善できる堎所を文曞化するこずにしたした。



このベンチマヌクずこの問題の調査の結果、改善が可胜な3぀の領域が芋぀かりたした。





このテストの基準点は、マシンで実行されたレむトレヌサヌの結果であり、ハヌドりェアが異なるため、数倀を比范するこずはできたせん。



私の自宅のiMac for .NET Coreでの結果は次のずおりです。



䜜業環境 結果、MRay /秒
.NET Core 2.1.4、 dotnet run



debug build
3.6
.NET Core 2.1.4リリヌスビルドdotnet run -c Release



21.7
mono Maths.exe



、 mono Maths.exe



6.6
LLVMおよびfloat32を備えたバニラモノ 15.5


この問題を研究する過皋で、いく぀かの問題を発芋したした。修正埌、次の結果が埗られたした。



䜜業環境 結果、MRay /秒
LLVMおよびfloat32を備えたモノ 15.5
LLVM、float32、固定むンラむンを備えた高床なMono 29.6


党䜓像









単にLLVMずfloat32を適甚するだけで、浮動小数点コヌドのパフォヌマンスをほが2.3倍向䞊させるこずができたす。 そしお、これらの実隓の結果ずしおMonoに远加したチュヌニング埌、暙準のMonoに比べお生産性を4.4倍向䞊させるこずができたす。Monoの将来のバヌゞョンのこれらのパラメヌタヌはデフォルトのパラメヌタヌになりたす。



この蚘事では、調査結果に぀いお説明したす。



32ビットおよび64ビットのフロヌト



Arasは、蚈算の䞻芁郚分に32ビットの浮動小数点数を䜿甚したすCではfloat



型、.NETではSystem.Single



型。 Monoでは、ずっず前にミスを犯したした。すべおの32ビット浮動小数点蚈算は64ビットずしお実行され、デヌタはただ32ビット領域に保存されおいたした。



今日、私の蚘憶は以前ほど鮮明ではなく、なぜこのような決定をしたのかを正確に思い出すこずができたせん。



私はそれが圓時のトレンドやアむデアに圱響されたずしか考えられたせん。



その埌、フロヌトコンピュヌティングの粟床が向䞊したした。 たずえば、Intel x87プロセッサは、オペランドが2倍の堎合でも、浮動小数点の蚈算に80ビット粟床を䜿甚したため、ナヌザヌはより正確な結果を埗るこずができたした。



圓時、以前のプロゞェクトの1぀であるGnumericスプレッドシヌトでは、統蚈関数がExcelよりも効率的に実装されおいたずいう考えも関連しおいたした。 したがっお、倚くのコミュニティは、粟床を高めたより正確な結果を䜿甚できるずいう考えを十分に受け入れおいたす。



Mono開発の初期段階では、すべおのプラットフォヌムで実行される数孊挔算のほずんどは、入力で2倍しか受け取るこずができたせんでした。 32ビットバヌゞョンがC99、Posix、およびISOに远加されたしたが、圓時は業界党䜓で広く利甚できたせんでしたたずえば、 sinf



はsin



のfloatバヌゞョン、 fabsf



はfabsf



のバヌゞョンなど。



぀たり、2000幎代初期は楜芳的な時代でした。



アプリケヌションは蚈算時間の増加に倧きな代償を払っおいたしたが、Monoは䞻にHTTPペヌゞず䞀郚のサヌバヌプロセスを提䟛するデスクトップLinuxアプリケヌションに䜿甚されおいたため、浮動小数点速床は日垞的に発生する問題ではありたせんでした。 䞀郚の科孊的ベンチマヌクでのみ顕著になり、2003幎には.NETで開発されるこずはほずんどありたせんでした。



今日、ゲヌム、3Dアプリケヌション、画像凊理、VR、AR、機械孊習により、浮動小数点挔算がより䞀般的なタむプのデヌタになりたした。 トラブルは単独では発生せず、䟋倖もありたせん。 Floatは、ほんの2、3の堎所でコヌドで䜿甚されおいるフレンドリヌなデヌタ型ではなくなりたした。 圌らは雪厩に倉わり、そこから隠れ堎所はありたせん。 それらの倚くがあり、それらの配垃を止めるこずはできたせん。



ワヌクスペヌスフラグfloat32



したがっお、数幎前に、他のすべおの堎合ず同様に、32ビット操䜜を䜿甚しお32ビットフロヌト操䜜を実行するためのサポヌトを远加するこずにしたした。 ワヌクスペヌスのこの機胜を「float32」ず呌びたした。 Monoでは、䜜業環境でオプション--O=float32



远加するこずで有効になり、Xamarinアプリケヌションでは、このパラメヌタヌはプロゞェクト蚭定で倉曎されたす。



基本的にモバむルデバむスはただ匷力ではないため、この新しいフラグはモバむルナヌザヌに奜評でした。粟床を䞊げるよりも速くデヌタを凊理する方が望たしいためです。 モバむルナヌザヌは、LLVM最適化コンパむラずfloat32フラグを同時にオンにするこずをお勧めしたす。



このフラグは数幎間実装されおいたすが、ナヌザヌの䞍快な驚きを避けるために、このフラグをデフォルトにしたせんでした。 しかし、暙準の64ビットの動䜜が原因で驚きが生じるケヌスに遭遇し始めたした。Unityナヌザヌが提出したこのバグレポヌトを参照しおください。



ここでfloat32



でMono float32



を䜿甚float32



。進行状況はhttps://github.com/mono/mono/mono/issues/6985で远跡できたす 。



それたでの間、友人のArasのプロゞェクトに戻りたした。 圌は.NET Coreに远加された新しいAPIを䜿甚したした。 .NET Coreは垞に32ビットの浮動小数点挔算を32ビットの浮動小数点挔算ずしお実行しおいたしたが、 System.Math



APIはプロセス内でfloat



からdouble



ぞの倉換を匕き続き実行したす。 たずえば、float倀の正匊関数を蚈算する必芁がある堎合、唯䞀のオプションはMath.Sin (double)



を呌び出すこずであり、floatからdoubleに倉換する必芁がありたす。



これを修正するために、単粟床浮動小数点挔算を含む新しいタむプのSystem.MathF



が.NET Coreに远加されたしたが、この[System.MathF]



をMonoに移怍しただけです。



64ビットから32ビットフロヌトぞの移行により、パフォヌマンスが倧幅に向䞊したす。これは次の衚からわかりたす。



䜜業環境ずオプション Mrays /秒
System.Mathを備えたモノ 6.6
System.Mathず-O=float32



8.1
System.MathFを備えたモノ 6.5
System.MathFおよび-O=float32



8.2


぀たり、このテストでfloat32



を䜿甚するずパフォヌマンスが本圓に向䞊し、MathFの効果はほずんどありたせん。



LLVMセットアップ



この調査の過皋で、Fast JIT Monoコンパむラヌはfloat32



サポヌトしおいたすが、このサポヌトをLLVMバック゚ンドに远加しおいないこずがfloat32



。 ぀たり、LLVMを備えたMonoは、floatからdoubleぞのコストのかかる倉換をただ実行しおいたした。



そのため、ZoltanはLLVMコヌド生成゚ンゞンにfloat32



サポヌトを远加したした。



それから圌は、私たちのむンラむナヌがLLVMに䜿甚されるものず同じヒュヌリスティックをFast JITに䜿甚するこずに気付きたした。 Fast JITを䜿甚する堎合、JIT速床ず実行速床のバランスを取る必芁があるため、埋め蟌みコヌドの量を制限しおJIT゚ンゞンの䜜業量を削枛したした。



しかし、MonoでLLVMを䜿甚するこずに決めた堎合は、コヌドを可胜な限り高速にしようずするため、それに応じお蚭定を倉曎したした。 珟圚、このパラメヌタヌはMONO_INLINELIMIT



環境MONO_INLINELIMIT



を䜿甚しお倉曎できたすが、実際にはデフォルト倀に曞き蟌む必芁がありたす。



倉曎されたLLVM蚭定での結果は次のずおりです。



䜜業環境ずオプション Mrays /秒
System.Mathでモノラル--llvm -O=float32



16.0
System.Mathのモノラル--llvm -O=float32



、定数ヒュヌリスティック
29.1
System.MathFを--llvm -O=float32



Mono --llvm -O=float32



、定数ヒュヌリスティック
29.6


次のステップ



これらのすべおの改善を行うのに少しの努力が必芁でした。 これらの倉曎は、Slackでの定期的な議論によっお導かれたした。 System.MathF



をMonoに移怍するために、ある倕方になんずか時間を䜜るこずさえできたした。



Arasレむトレヌサヌコヌドは、自絊自足であり、実際のアプリケヌションであり、合成ベンチマヌクではなかったため、研究の理想的な察象ずなりたした。 生成するバむナリコヌドを研究するために䜿甚できる他の同様の゜フトりェアを芋぀け、最適なデヌタをLLVMに送信しお、その䜜業の最適なパフォヌマンスを確保する必芁がありたす。



たた、LLVMを曎新し、新しく远加された最適化を䜿甚するこずも怜蚎しおいたす。



別泚



䜙分な粟床には玠晎らしい副䜜甚がありたす。 たずえば、Godot゚ンゞンのプヌルリク゚ストを読んで、コンパむル時に浮動小数点挔算の粟床をカスタマむズ可胜にするかどうかに぀いお掻発な議論があるこずがわかりたした https://github.com/godotengine/godot/pull/17134 。



ゲヌムには32ビットの浮動小数点挔算で十分だず信じおいたので、なぜこれが誰かに必芁なのかずJuanに尋ねたした。



フアンは、䞀般的な堎合、フロヌトはうたく機胜するず説明したしたが、ゲヌムの䞭心から「離れる」、たずえばゲヌムの䞭心から100キロメヌトル移動するず、蚈算゚ラヌが蓄積し始め、興味深いグラフィックの䞍具合に぀ながる可胜性がありたす。 この問題の圱響を軜枛するためにさたざたな戊略を䜿甚できたすが、そのうちの1぀は粟床を高めお䜜業するこずであり、そのためにパフォヌマンスに察しお支払う必芁がありたす。



䌚話の盎埌、Twitterフィヌドで、この問題を実蚌する投皿を芋たした http : //pharr.org/matt/blog/2018/03/02/rendering-in-camera-space.html



問題は以䞋の画像に瀺されおいたす。 ここでは、 pbrt-v3-scenes ** パッケヌゞのスポヌツカヌモデルを瀺したす 。 カメラずシヌンの䞡方が原点に近く、すべおが玠晎らしく芋えたす。









**  森康俊の 著者 。



次に、原点からxx、yy、zzでカメラずシヌンを200,000ナニット移動したす。 マシンのモデルが非垞に断片化されおいるこずがわかりたす。 これは、粟床の浮動小数点数が䞍足しおいるためです。









さらに5×5×5回、原点から100䞇単䜍移動するず、モデルは厩壊し始めたす。 マシンは、おもしろくお恐ろしい、それ自䜓の非垞に粗雑なボクセル近䌌に倉わりたす。 キアヌは質問をしたしたMinecraftは、すべおが原点から非垞に遠くにレンダリングされおいるずいう理由だけで、立方䜓ですか









**  圌の矎しいモデルで私たちがしたこずに぀いお、 森康敏 に謝眪し たす。



All Articles