1 of 26

Rustによる数値計算の

現状と課題

@termoshtt

2 of 26

数値計算とは?

  • 理学・工学の問題の多くは紙とペンでは解けず、数値的に解く必要がある
    • 流体・固体の応力・熱伝導(CAE = Computer Aided Engeenering)
    • タンパク質分子の活性(量子化学計算)
    • 気象・海洋の運動
    • などなど...
  • 問題毎に個別にソフトウェアを作る必要がある
    • 計算機があったら計算できるわけではない
    • 実装するには問題に応じて量子科学や気象モデルのような専門的な知識が必要
    • 大規模な計算が必要になるケースも多く、スパコン(独自CPU+MPI)のような特殊な環境で動かす必要がある
  • データ分析のように対話性が重要になるタスクとは少し性質が違う
    • 一つの計算に数日から数週間レベルの規模の計算を行う事が多い
    • 数値計算の出力を分析する必要があるので連携は大事

3 of 26

典型的な数値計算プロジェクト

  • 理論の専門家でプログラミングも出来る人が作る
    • 商用のコードとしてベンダー会社が継続的にメンテされるものが多い
    • 短期的な国家プロジェクト(科研費やCREST)等でチームで作ることもある
    • 研究室で過去のメンバーが作った独自コードをメンテ(?)しながら使っていたりもする
    • OSSとして公開されてメンテされいるものもある
  • C++ / Fortran / MATLABが多い
    • 性能が必要になる
      • 数日から数か月かかる計算も多いので数%の高速化でも意味が出てくる
    • そもそもスパコンのコンパイラがFortranしか対応してないとかも多い
    • 最近のスパコンはNVIDIA GPU構成が多くCUDAが直接かける必要がある
    • 計算手法の提案レベルではMATLABも多い
    • 最近はPythonのラッパーが付いている事も多い

4 of 26

Why Rust? (言語仕様)

5 of 26

Why Rust?(言語仕様)

  • LLVMを通して最適化するのでCと同程度に高速
    • Thin-LTOとかも使える
    • clangで出来ることはおおよそ全て出来る
    • LLVMバックエンドがあるCPUで動作出来る
  • 強い型付け
    • マルチスレッドを前提とした型システム(可変参照の単一化, Sync/Sendマーカー)
  • Traitを用いた抽象化
    • 特定の性質を持った型に対してアルゴリズムが記述できる
    • 数学的な前提条件の書き方と相性がいい
  • メモリに対する完全な管理権限
    • GCが入らないので、全て自分で操作できる
    • マシンにのるギリギリの計算を行う場合には必要な機能
    • C++より単純化されたmoveセマンティクス

6 of 26

並列化・SIMD

  • nikomatsakis/rayon
    • データを分割統治し、Intel Clikと同様のwork stealingによるデータ並列ライブラリ
    • iter() を par_iter() に変更するだけで並列化される簡易APIもある
  • std::archを使ってSIMD命令が実行出来る
    • 関数レベルで条件付コンパイルが可能
    • 実行時にCPUの機能を判定する事も可能
    • Stable Rustで動くのはx86/x86_64のみ
    • Inline asmはサポートされず、コンパイラのIntrinsicsとして追加する必要がある

7 of 26

数値型: num-traits

  • 演算子は Add<T> 等のTraitで実現
  • num-traitsに便利なTraitがある
    • Zero
    • One
    • Num, NumOps, NumAssign
    • ToPrimitive, FromPrimitive, NumCast
    • Float
  • 複素数まで統合して扱う為に cauchy::Scalar というTraitを実装した
    • A::Real のような処理が固有値分解などで必要となるので

8 of 26

Traitを使ってアルゴリズムを実装する(1)

  • 常微分方程式を積分するためのRunge-Kuttaというアルゴリズムを実装する
    • アルゴリズム自体はどんな方程式かによらない
    • なのでどんな方程式が来ても積分出来るコードにしたい
  • 方程式をいれたら積分方法を知らずに積分された結果だけが欲しい
    • f(x, t) の実装だけしかしたくない
    • 後からRunge-Kutta公式の次数を指定するだけで実装を切り替えたい
    • 積分する機能を使ってさらに高次の機能(分岐追跡、リアプノフ解析など)を実装したい
  • Runge-Kuttaを使って積分出来る運動方程式のTraitを定義しよう!
    • termoshtt/eom

9 of 26

Traitを使ってアルゴリズムを実装する(2)

10 of 26

Traitを使ってアルゴリズムを実装する(3)

11 of 26

Traitを使ってアルゴリズムを実装する(4)

12 of 26

Traitを使ってアルゴリズムを実装する(5)

13 of 26

Traitを使ってアルゴリズムを実装する(6)

14 of 26

既存プロジェクトの利用: Foreign Function Interface

  • C/C++/Fortranでの実装を使いたい
  • alexcrichton/cc-rs
    • Rustのビルドシステム内(build.rs)でC/C++のコードをコンパイルしてリンクしてくれる
    • 少数のコード片ならこれが非常に楽
  • 共有ライブラリ(*.so, *.dll)をリンクして使うことは出来る
    • 関数名の解決とリンクを頑張れば呼べる
    • 数値計算に限らず、多くのcrateでCで作った標準的なライブラリを使用している
    • ex. alexcrichton/xz2-rs (liblzmaのバインディング)
  • rust-lang/rust-bindgen
    • CのヘッダーからRustのバインディングを自動生成してくれる
    • LAPACKやFFTWのバインディングはこれで生成している

15 of 26

Why Rust?(開発環境)

16 of 26

Why Rust?(開発環境)

  • パッケージ管理機構がある、ライブラリが容易に使える
    • Cargo.tomlファイルに使うライブラリを書いたら勝手にインストールされてリンクされる
      • もちろん依存ライブラリの依存ライブラリも自動的に入る
      • Semantic Versioningによってある程度の互換性も維持される
    • この機能は極めて大事で、これにより既に誰かが解決している問題を不完全な形で再発明する事を避けられる
  • 普及しているプログラミング言語としての恩恵はそのまま得られる
    • 数値計算に固有の問題はそれ程多くなく、一般的なソフトウェア開発における問題に対する解決策をそのまま使える事は有益
      • パッケージ管理機能もその一つ
      • OSSとしてのメンテナンスコストの低減は重要な課題

17 of 26

Mathematical/Scientific Rust crates

  • rust-num
    • num-traits:数値向けのTrait集
    • num-complex:複素数
  • rust-ndarray
    • ndarray : numpy.ndarray的なストライドベースの多次元配列
    • ndarray-linalg:numpy.linalg相当
    • vbarrielle/sprs:疎行列
    • petgraph/petgraph: Graph data structure library
  • rust-math
    • sfmt: メルセンヌツイスタのRust実装
    • intel-mkl-src:Intel MKLをリンクする
  • PyO3
    • pyo3:Rustで実装した関数をPythonから呼べるようにする
    • rust-numpy/rust-numpy: PyO3のNumPy対応

18 of 26

Benchmarking

  • bheisler/criterion.rs
  • Stable Rustでベンチマーク機能が使える
  • ベンチマークで取った値を統計処理までする
  • 前回との比較も取れる

19 of 26

criterion-rs

  • target/reportにHTMLのレポートが出来る

  • 経過時間の分布
  • 平均・分散
  • etc...

20 of 26

Performance Profiling: FlameGraph

  • perfを使って関数毎の消費時間をサンプリング
  • 消費時間を呼び出しの依存性に応じてプロット

21 of 26

Rustを数値計算で使う際の課題

22 of 26

Rustで数値計算やってみた感想

  • Pros
    • 開発環境がとにかくありがたい
    • 数値計算のコードは研究が進むにつれて大規模な仕様変更が頻繁に発生するが、コンパイラの指示に従って直すと自動的に正しく直される
    • Traitがあるので数値アルゴリズム的なレベルでライブラリが書きやすい
    • 何人かの先駆者のおかげでグラフや疎行列のライブラリはある
  • Cons
    • 数値計算にはまだあまり使われておらず、Pythonのようにライブラリが充実はしてない
    • PythonやC++に比べると書いてる人が少ないので情報が少ない
    • GPU・アクセラレータに対応していない
    • スパコンのような特殊なコンパイラが必要な環境で使えない

23 of 26

GPUやアクセラレータへの対応

  • 大規模計算機の多くがGPUかアクセラレータ構成
  • CUDA/C++, OpenACC等のコンパイラ拡張で実装する
  • 他の言語のサポートは無い

24 of 26

rust-cuda working group

  • プラットフォーム毎にサポートのレベルがある
    • Tier1: Guaranteed to work
      • x86_64-unknown-linux-gnu, x86_64-pc-windows-msvc, etc...
    • Tier2: Guaranteed to build
      • aarch64-unknown-linux-gnu, armv7-unknown-linux-gnueabihf, etc...
    • Tier3: Rust codebase has support for, but which are not built or tested automatically.
      • nvptx64-nvidia-cuda, etc...
  • nvptxターゲットをTier2にする事を目指している
    • あまり活動出来てない...
  • rust-cuda/cuda-sys
    • CUDA (8.0) Driver/Runtime APIのRust binding

25 of 26

まとめ

26 of 26

Rustによる数値計算の現状と課題

  • 言語仕様
    • LLVMによる最適化、メモリの管理に対する権限
    • Traitを使ったプログラミングによって、数値計算のアルゴリズム自体の普遍的な性質を抽出する事に集中できる
  • 開発環境
    • rustup/cargoの公式ツールセットが非常に充実している
    • ベンチマーク、ホットスポット解析用のツール群
  • 課題
    • ライブラリの充実
    • GPU・アクセラレータ対応
  • コミュニティ
    • rust-jp slackに #scientific チャンネルを作ったので適当に聞いてください(´・ω・`)