PythonはAIやデータ分析などで広く使われ、すばやくコーディングできるという利点がありますが、インタプリタ言語に付きものの速度低下の問題のせいで、実務では悩みの種になることもあります。
実務ではPythonの速度問題を改善するために、さまざまな代替案が検討されます。Pythonコードは初期プロトタイプとしてだけ使い、productionへ移行する際にRustやC/C++で作り直すこともあります。
私はPythonを捨てずに速度問題を解決する新たな選択肢として、Rextioというツールを実験的に開発しています。
基本的なコンセプトは、Pythonコードのうちネイティブへ変換可能な部分(型ヒント付きの静的なコードなど)をRustコードへ自動変換してからバイナリにコンパイルし性能を高め、ネイティブへの自動変換が難しい部分(動的なコードなど)はそのままPythonコードとして残して(fallback)CPythonで実行させることで、元のPythonコードのロジックを保持するというものです。
大まかには次のようになります。
型が指定されたPythonプロジェクト
-> サポートされるnative候補を解析
-> 安全でない、または未サポートの関数は拒否
-> 受理された関数は Rust + PyO3 を生成
-> 残りは Python fallback wrapper を生成
-> import互換のartifactをビルド
詳しくはリンク先のGit repositoryのドキュメントを参照してください。
Rextioで変換したnativeバイナリを含めて実行した場合と、元のPythonコードをCPythonで実行した場合を比べると、性能向上も確認できます。
- 基本的なPythonコードをnativeに変換して実行時: 57.73×
- NumPyをnativeに変換して実行時: 2.52×
- NetworkXをnativeに変換してDijkstraアルゴリズムを実行時: 3.68×
- pandasの
Series.mapをnativeに変換して実行時: 66.14× - PyTorch deep MLPをnativeに変換して実行時: 1.02×(既存のPythonパッケージでC拡張などが使われており、速度向上は限定的)
- TensorFlow eager chainをnativeに変換して実行時: 1.04×(既存のPythonパッケージでC拡張などが使われており、速度向上は限定的)
上記結果が得られたベンチマークで使用したソースコードと実行環境の情報は、rextio-benchmark Git repositoryを参照してください。
参考までに、RextioにはPythonコードを変換してコンパイルを実行するCore CLIがあり、そこへ個別のPythonパッケージをRustコードへ変換するルールを定義した追加プラグインを作って組み込めるように開発しています。現在はNumPyなどのプラグインを一部作成しており(rextio-numpy, rextio-networkx, rextio-pandas, rextio-torch, rextio-tensorflow など)、上記ベンチマーク結果はこれらのプラグインを活用して実行した結果です。
もちろん、Rextioはまだ改善点の多い初期プロジェクトであり、あらゆる状況でPythonコードをRustベースのnativeにコンパイルすれば性能が向上するというわけではありません。
たとえばnative部分とCPython fallback部分のデータ交換が頻繁な場合、データ変換を伴って境界をまたぐため、かえって速度低下が発生することがあります。ただしRextioでは、このような場合にはその部分をnative経由にせず全面的にCPythonへfallbackさせることで、速度低下を防ぐようにしています。
これまで一人で開発してきましたが、ある程度形になってきたと思い、ここで紹介します。
質問や意見、フィードバックをいただければ、できる限り回答し、反映できるよう努めます。
ありがとうございます。
まだコメントはありません。