TL;DR
Pythonで3分かかっていた数値計算・約800万行のテキストファイル書き出し処理をRustに置き換えたら約5倍速くなった
はじめに
上記はこちらの記事でも紹介した、日本の地域メッシュを.geojsonl形式で生成するPythonモジュールです。標準モジュールのみで書けるくらい純粋な数値計算ですが、たとえば3次メッシュでは800万弱のポリゴン数となり、後述しますが所要時間は3分くらいになります。
このPythonの処理をRustに置き換えたらどれくらい速くなるのか、Rustの勉強を兼ねて試してみました。ちなみにRustのコードも上記のリポジトリに含まれています。
参考:Python上での高速化を検討
アルゴリズムをいじっても劇的な速度改善とはなりませんでした。Python自体インタプリタ言語ですし、速度を求めるべきではないでしょう。また、numpyを使えばC言語の力を借りて速くなるでしょうが、外部モジュールへの依存なしの状態を保ちたかったためボツとしました。
Python vs Rust 速度比較
テスト条件
- macOS: Core i7 9750H RAM:16GB
- 3次メッシュを日本全域で生成する
- Python 3.8.3
- Rust 1.43.0
- Rustはreleaseビルドした実行ファイルで測定する
ファイッ!
Python
time python main.py 3
initializing...
making meshes...
writing file...
done
real 2m46.227s
user 2m31.846s
sys 0m11.249s
166.227秒
Rust
time ./target/release/japan-mesh 3
real 0m35.955s
user 0m34.233s
sys 0m1.272s
35.955秒
結果
35.955/166.227=21.63006%
約5倍の高速化!
Rustについて
なぜRust?
- 速いらしい
- 今アツいらしい
これくらいの軽い理解で始めました。今考えると、何より魅力的なのは、環境構築の容易さだと思います。コマンド一発でコンパイラやパッケージマネージャとか全部入ります。
Rustって難しいんでしょう?
多少かじったくらいですが、Pythonよりは難しいです。ただRustを難しくしているのは所有権システムやライフタイムやらの概念で、今回のようなただの数値計算なら、コンパイラに怒られながらも動くものは作れます。
感想
- アレなコードになってるはずのRustでもちゃんと速いのがうれしい
- 当然ながら計算部分の速度差は歴然だが、ファイル書き出しはそんなに変わらなそう
- Rustはコンパイラが優秀でおかしなコードを書くと怒ってくれる
- いずれもコードに最適化の余地があると思う
- 当初はgeorust/geojsonを使っていたが、to_string()がとても遅かった