MPI環境の切り替えをするmpienvというツールを作った
背景
多くの場合、スパコンやクラスタ上には複数のMPIがインストールされています。ユーザーは、これらを適切に切り替えて使わなければなりません。普通のユーザーであれば、普段使うMPIは一種類で固定であるケースが多いので、.bashrc
等の設定ファイルに設定を書いておけば問題ありません。
ライブラリなどの開発をする場合、複数のMPIでテストを行う必要があるので、MPIを切り替えて使うことになります。基本的にはPATH
とLD_LIBRARY_PATH
を切り替えればOKなのですが、プログラムをコンパイルしたときのMPIと、実行するときのMPIは合致していなければいけません。これらが食い違うと、正しく並列プログラムを実行できません。
基本的には2つの環境変数を切り替えるだけですので、シェルスクリプトでも書けば一瞬ですし、環境によっては実際に既に用意されていることも多いです。プラットフォーム固有の切り替えコマンドがある場合もあります(例えばCray系システムのmodule
コマンドなど)。
解決すべき問題
このような、複数のMPIの利用にはいくつか問題があります。
- システムにどのようなMPIが用意されているのか忘れる
- あるプログラムをどのMPIでコンパイルしたのか忘れる
- MPIの切り替えを手動でやろうとして忘れる
- 自分でインストールしたMPIの存在を忘れる
のような問題です。
さらに、PythonからMPIを使うライブラリであるmpi4py
を用いると、さらなる問題が発生します。mpi4pyはインストール時に使ったMPIにリンクされるため、PATH
とLD_LIBRARY_PATH
を切り替えるだけでは駄目だということです。切替時には、mpi4pyを一旦アンインストールし、MPIを切り替えたあとに再度mpi4pyをインストールする必要があるということです。
pyenv
などのツールを使ってPython実装ごと切り替えるという手もありますが、それはかなり面倒ですし、どちらにしろpyenv
による切り替えを忘れると謎のエラーで苦しむ事になります。
解決策
これらを解決するために、mpienv
というツールを作りました。これは、Pythonにおけるpyenv
だと思っていただければ、ほぼ正しいです。
詳細はREADMEを見ていただきたいと思いますが、基本的にできることは以下です。
- システムにインストールされているMPIを一覧・管理する
- MPIを切り替える
- mpi4pyも同時に切り替える
- 開発中の機能
- MPIを自動でインストールする
- バイナリを指定した時に、それに適したMPI実装を自動で選ぶ
pyenv
のように、ディレクトリごとに使うMPIを切り替える
などのことができます。手前味噌ですが、複数MPIを切り替えてのテストやデバッグが劇的に楽になりました。まだまだ開発中ですが、適当なタイミングで利用方法の説明を書きたいと思います。
Raspberry Pi3 Model Bを買った
ちょっと前から興味があったので、Raspberry Pi3 Model B を購入しました。
Raspberry Pi3 Model B ボード&ケースセット 3ple Decker対応 (Element14版, Clear)-Physical Computing Lab
- 出版社/メーカー: TechShare
- メディア: エレクトロニクス
- この商品を含むブログ (4件) を見る
ARMアーキテクチャ上での数値演算の最適化とか、エミュレーター書いてみたいとかいろいろ興味があります。 CPUは4コアのARM Cortex-A53、クロックサイクルは1.2GHz。
ポスト京スーパーコンピューターもARMアーキテクチャですしね。
もちろんラズパイで数値演算しても 実用上は意味ないのですが、ARMアーキテクチャについていろいろ勉強してみたいところです。 SVE(Scalable Vector Extension)を理解する上でも、基本的なARMアーキテクチャについてわかってないとダメですし。
ということでしばらく遊んでみます。
数値微分(Juliaで)
Juliaで数値微分を書いてみます。
数値微分の基本
数値微分は、直感的には微小幅 について関数の値を計算して差分を取れば、それが勾配になります。しかし、数学的にもう少しちゃんと根拠が示されています。
まず、微分を求めたい1変数関数を 、点をとします。そして、微小幅 について、関数 を の周りでテイラー展開します。
ただし、は、 以上の項です。同様に、関数 をの周りでテイラー展開します。
ここで上2つの式を引き算すると、都合の良いことに の項が消えます。
以上の項を無視することによって、
という結果が得られました。これは中心差分の公式と呼ばれます。上の式変形からわかるように、の項まで考慮しているので(計算の途中で消えたけどw)、誤差のオーダーが (二次精度)となります。
Juliaで実装
上式をJuliaで実装してみます。Float32
をベースとして使って、 としてJuliaの組み込み定数であるeps(Float16)
を使ってみます。
コード自体は非常に単純です。
function diff(f) h = eps(Float16) return (x -> (f(x+h) - f(x-h))/(2h)) end
受け取った関数 の1次の導関数を返します。試しに、いくつか解析的に自明な関数の計算をしてみます。
julia> f = x -> x # 恒等関数:微分係数は常に1 (anonymous function) julia> df = diff(f) (anonymous function) julia> df(0) 1.0f0 julia> df(1000) 1.0f0 julia> g = x -> x^2 + 3x + 1 # g(x) = x^2 + 3x + 1 (anonymous function) julia> dg = diff(g) # 導関数は g'(x) = 2x + 3 (anonymous function) julia> dg(0) 3.0f0 julia> dg(5) 13.0f0 julia> h = x -> sin(x) # h(x) = sin(x) (anonymous function) julia> dh = diff(h) # 導関数は h'(x) = cos(x) (anonymous function) julia> dh(0) # cos(0) = 1 0.9999998f0 julia> dh(pi/2) # cos(π / 2) = 0 0.0
なんとなく良さそうです。