まえがき
私はREPLやJupyterのようなものを使わず、専らファイルを実行してデバッグするのでJuliaのように初回ロードが遅いけど2回目から早いよ!っていう言語ではその恩恵が受けにくい。というかプロットパッケージのロードに10秒くらいかかってメモリも1GiBも使うようでは遅すぎて話にならない。なぜ遅いのかというと、初回ロード時にJIT(Just In Time)コンパイルをしており、巨大なパッケージだとここで時間がかかる。しかし、2回目以降の実行ではコンパイル済みなのでC並の速度が出る。だとすれば、1回目にコンパイルと言わず、0回目、つまりロードする前にコンパイルしておけばいいのである。ここで、Juliaは言語のある程度をJulia自身で記述しているが、Juliaのインタプリタ(この言い方が適切かどうかは怪しい)は実行開始時にJuliaの言語体系すべてをコンパイルしているわけではない。そんなことをすれば一生ロードが終わらなくなってしまう。そこで言語の基本機能をシステムイメージとしてロード済みの環境をバイナリで保存し、それをプログラム実行時に読み込むことで言語基本機能のロードを高速化している(おそらくこのシステムイメージはJuliaインストール時に生成されている)。それならば、事前によく使うパッケージもロードした環境をシステムイメージ(カスタムシステムイメージ)として保存しておけばよいというのが今回の話である。
想定する環境
- Ubuntu 20.04 LTS
- Julia 1.4.1
- “PackageCompiler” => v”1.1.1”
まずはプログラムが動くように
main.jl
に次のようなプログラムが書かれているとする。
1 |
|
このファイルは
1 | julia main.jl |
とすることで実行できるが、この出力は以下のようになり、パッケージのロードに非常に時間がかかっている。
カスタムシステムイメージを作る
カスタムイメージの作成に必要なパッケージをインストールしておく
1 | sudo apt install libjulia-dev |
julia REPLに入る
1 | $ julia |
PackageCompiler
というパッケージがカスタムシステムイメージを作ってくれるのでインストールする。PackageCompiler.create_sysimage
関数を使用してシステムイメージを作成する。第一引数にはimport
やusing
で使うパッケージを指定する。複数ある場合は,
で区切る。sysimage_path
は生成するシステムイメージの場所。precompile_execution_file
はここで指定されたプログラムを実行するときにロードするものをすべてプリコンパイルするという意味。
以上でカスタムイメージが生成されたはずだ。
システムイメージを使う
1 | julia -J sys.img main.jl |
ロード時間がかなり短縮されたはずだ。
あとがき
この手順を踏まないとまともにロードできないとなるとまだJuliaは発展途上と言わざるを得ない。だが、構文やJITコンパイルの機能などは優れていると思うのでこれからの発展を願うとともに、Pythonエコシステムのバランスの良さに改めて気付かされた。Pythonはfor
が遅いとよく言われそれは事実であるが、Cで書かれたパッケージを用いることでその点は概ね解消でき得る。また、Juliaのような未熟なシステムを本番環境で使うわけにはいかないので、多かれ少なかれJuliaは開発段階での使用に留まるだろう。その点ではPythonも同様であるが、PythonはデバッグがJuliaよりも圧倒的に優れている。そのため開発効率としてはPythonのが上手であると思われる。製品版ではどのみちPythonも使わずCかC++で書くだろうから、Juliaを使わずに開発にPython、製品にC/C++のほうが余計なことを考えずに済むので楽かもしれない。