2020年9月21日月曜日

プログラミング言語Juliaは速い速いと言うけれども

このエントリーをはてなブックマークに追加
Clip to Evernote
Pocket

科学技術演算分野で急速に利用が進んでいるプログラミング言語Juliaは、MatlabやPython、Rなどと比較すると文字通り桁違いに速い。しかし、勢い余って「Cのような高速な言語に匹敵するほどの実行速度を持つ」と言い出す人々が出現してきた。誇張が過ぎるか、自分でコーディングをして比較していないので、どういう条件でJuliaの速いと言えるかが理解できていない。

マイクロベンチマークを取るとJuliaがCやFortranの数割遅れぐらいの速度を出すのは事実なのだが、実行するコードが複雑になってくると速度差が開く傾向がある。個人の異質性が入ったマクロ経済学のある数値計算では*1、計算中間に使うグリッドサイズが小さい低精度版ではRとC拡張で構成されたコードに対してJuliaは2割遅れぐらいで済んでいたが、高精度版では3倍ぐらいの差がついた*2。高精度版でRとC拡張 : Julia : R = 1 : 3 : 47のような経過時間差なので、Juliaは十分に速いと言えるが、C/C++/Fortranとの差は確かにある

他のモデルで、RとC++の拡張で書いたコードは、Juliaで書いたコードよりも(利用した疎行列の固有値問題ソルバーの性能差が大きいと思うが)3.7倍速かった。速さだけで評価したら、C++やFortranを使うのがベストと言う事になる。Juliaの良さは、単に速い方だということではなく、その速さで多様なパッケージを利用できることにある。Rcpp/Eigenを使えば、ファイル入出力やデータ加工処理、プロットなどの速度が要らないが煩雑な部分をRで書きつつ、Juliaもぶっちぎったパフォーマンスをたたき出す事ができるわけだが、C++で書かれた部分で細々としたライブラリの不足に悩む可能性がある。

単純な構造のループ地獄をC/C++拡張で速くするわけだが、実際は言うほど単純ではないことも多い。所要時間で3.7倍の差がついたMatlabで書かれた教科書的なコードの移植作業でも、(この世のどこで配布しているか分からなかったので)線形補間、3次元スプライン補間、(Matlabのpchip互換の)区分的3次エルミート内挿多項式のC++のコードを作成することになったし、線形代数まわりは定番ライブラリのEigenで済むかと思ったが、別に疎行列の固有値問題ソルバーを探さないといけなかった*3。書き続けていけば自分が使うライブラリは整備されていくので問題解決するが、プログラミングが好きでない人は途中で挫折するかも知れない。Rの拡張の場合、パッケージの関数を含めたRで書かれたコードなども呼べたりするが、目的としている速度が犠牲になる。

RとC/C++拡張の世界の場合、RとC/C++のそれぞれでライブラリの整理をする必要があり、C/C++のライブラリは探してくるのが手間隙だったりする*4一方、Juliaの場合はJuliaのパッケージを探してくれば済む。実行しようとすると露骨にソースコードをコンパイルしだして待たされたりする*5し、変数スコープがうるさいので窮屈な感じがするし、微妙に仕様変更があって2年前に書かれたパッケージがそのままでは使えなくなっていたり、バージョン1.4xまで対話型インターフェイス(REPL)とJupyter Notebookの変数スコープの仕様が違っていたり、型推論を間違えた上に自動型変換しないのでいらっとするエラーが出たりするが*6、この点は楽。

*1経済セミナー連載の「定量的マクロ経済学と数値計算」のサポート・リポジトリーのMatlab、Julia、FortranのコードをRにポーティングしていた。

*2試して見る人は、RとC拡張版は3回演算し3本プロットしている一方で、Juliaバンは1回演算1本プロットになっている点に注意して、演算回数とプロットする線の数をそろえる必要があることに注意されたい。

*3標準では密行列用のソルバーしかなかったのだが、Spectraと言うEigen用のテンプレート・ライブラリがあって快調であった。なお、Eigen用には最尤法のソルバーとしてLBFGS++もあるし、ちょっと頑張ればC++/Eigenで計算は済むと言えば、済む。

*4ライセンスがうるさいので避けるべきな気がするが、ある定番テキストの付属コードをコピペして済ましている人が多い気配がある。

*53.7倍差になったコードでは、コマンドプロンプトでtime julia [スクリプトファイル]とやって計測すると、Juliaコードのメインループの経過時間が39.9秒なのに対して、timeコマンドの計測時間が1分20.9秒となったりする。同じ計算を行うRcpp/Eigenのコードだと、メインループが10.9秒で、timeコマンドは11.6秒。

*6条件文で数字と文字列を混同された悲劇を聞いたことがあるかも知れないが、自動型変換がプログラムが予期せぬ処理を実行する可能性があるので、Juliaのように厳しい方が正体不明のバグにはまって作業が前に進まない可能性は減るのだが、1のような数字を整数型と型推論して浮動小数点として扱おうとする文にエラーを出してこられるとむむむ・・・となる。

0 コメント:

コメントを投稿