Conda パッケージ管理

Python を使用したカスタム データや後処理分析のために Conda パッケージ管理の機能を活用するには、さまざまな方法があります。 このチュートリアルでは、Rescale でさまざまなアプリケーション用に Conda 環境をセットアップする方法について説明します。

お困りの方は Rescale Support にご連絡ください。

ミニコンダ対アナコンダ

Rescale で利用できる Conda 環境には XNUMX つの「タイプ」があります。XNUMX つは多数のプリインストールされたパッケージを含むもの (Anaconda)、もう XNUMX つは空の環境 (Miniconda) です。 ユーザーのニーズに応じて、どちらを使用してもさまざまな利点があります。 Miniconda 環境は、 , そのため、起動時間が短くなります。 これは、分析に XNUMX つまたは XNUMX つの異なる Python パッケージのみが必要な場合に理想的な選択肢となります。 CFD に加えてカスタム Python 後処理スクリプトを使用している場合 たとえば、Miniconda 環境で十分です。 分析に Anaconda 環境にプリインストールされたパッケージの多くが必要であることがわかっている場合は、クラスターの起動時間を追加する価値があると考えられます。そうでない場合は、クラスターが起動して実行されたらすべてのパッケージをインストールする必要があるためです。 どの環境を選択しても、Conda コマンドは同じように動作するため、ここにリストされているコマンドは Miniconda と Anaconda の両方で機能するはずです。

Rescale UI のコマンド ウィンドウで、次の行を追加できます。

conda install -y <package-name>

  -y flag はインストールを完了するために必要なため、含めることが重要です。 次のようにコマンドでパッケージのバージョンを指定することもできます。

conda install -y <package-name>=<version-num>

Anaconda ディストリビュータからの Conda インストール手順

この方法でインストールされたすべてのパッケージは、そのクラスター上で実行される Python スクリプトで呼び出すことができるようになります。 例えば:

conda install -y numpy=1.15.4python myscript_with_numpy_calls.py

追加の Python パッケージを使用する後処理用の Python スクリプトを実行したい場合は、追加のソフトウェアとして Miniconda を追加すると、Conda が必要なパッケージをすべてインストールします。 たとえば、何かを追加したい場合 後処理 可視化   matplotlib SU2 を実行すると、「ソフトウェア設定」ページは次のようになります。

SU2 タイルの場合:

Miniconda コマンドの場合。

一般に、Python スクリプトの並列化は自動的にマルチノード構成には拡張されず、通常は同じノード上で複数のシリアル プロセスを起動することに制限されます。 。 Rescale で大規模なクラスターを実行する機能を真に活用するには、何らかの種類の並列バックエンドを作成して管理する必要があります。 繰り返しますが、Conda は、このセットアップと必要なパッケージのインストールを支援します。 Conda パッケージ管理システムを使用する主な利点の XNUMX つは、Python の外部でパッケージをインストールおよび構成できることです。 これは、次のようなパッケージに必要な MPI など、低レベルのライブラリとの互換性が必要なパッケージをインストールするときに非常に有利になります。 mpi4py。 検討するアプリケーションは XNUMX つあり、XNUMX つは並列化が ipcluster 機械学習のトレーニングを加速するために使用されます 、および別の生の MPI 呼び出しを使用したもの mpi4py.

Python 並列環境のセットアップを開始する前に、Rescale でマルチノード クラスターをセットアップする方法について説明する必要がある詳細がいくつかあります。 必要なパッケージをすべて各ノードに個別にインストールするのではなく、マウントされた NFS に Conda 環境のクローンを作成することをお勧めします。 ~/work/shared ディレクトリ。 これを行うには、次のコマンドをジョブに追加します。

conda create -p ~/work/shared/uenv --clone uenvconda activate ~/work/shared/uenv... ... ワークフローを実行します ......rm -rf ~/work/shared/uenv

注: これは、クラスターに複数のノードが使用されている場合にのみ必要です。

次に、を実行すると、 conda install -p ~/work/shared/uenv -y <package-name> その後、そのパッケージはすべての計算ノードで利用できるようになります。 例えば:

conda create -p ~/work/shared/uenv --clone uenvconda activate ~/work/shared/uenvconda install -p ~/work/shared/uenv -y python myscript_with_package-name_calls.py rm -rf ~/work/shared/uenv

接頭辞フラグを追加する必要があることに注意してください -p ~/work/shared/uenv Conda がマルチノード クラスターにパッケージをインストールするときに、パッケージが正しい環境にインストールされるようにします。 また、仮想環境のクローンを共有ディレクトリに作成する場合は、クラスターに対話的に ssh 接続するときに仮想環境をアクティブ化する必要があります。 ジョブが完了したら、共有ディレクトリから Conda 環境を削除することが重要です。 rm -rf ~/work/shared/uenvそうでない場合、不要なファイルのアップロードが多数発生します。 繰り返しますが、単一ノードでのみ実行されている場合は、プレフィックス フラグ -p ~/work/shared/uenv 必要ありません。

次の手順では、ユーザーがマルチノード クラスター上で実行されることを前提としているため、Conda 環境は次の場所にあります。 ~/work/shared/uenv。 IpyParallel バックエンドをスピンアップするにはいくつかのパッケージが必要です。インストールの順序が重要になる場合があるため、常に次から始めることをお勧めします。 mpi4py & ipython.

conda install -p ~/work/shared/uenv -y mpi4pyconda install -p ~/work/shared/uenv -y ipythonconda install -p ~/work/shared/uenv -y ipyParallelconda install -p ~/work/shared/uenv -y numpyconda install -p ~/work/shared/uenv -y joblib

最初のステップは、NFS ドライブに新しいデフォルトの ipython ディレクトリを作成して、並列構成ファイルをすべてのノードに転送できるようにすることです。

import IPYTHONDIR=~/work/shared/.ipython

次に、新しいプロファイルを作成します。この場合、環境がクローン化されていると仮定します。 ~/work/shared/uenv それで私たちは ipython そこにある実行可能ファイル。

~/work/shared/uenv/bin/ipython プロファイル作成 --Parallel

コントローラーを開始するには、ヘッド ノードで次のコマンドを使用します。 から始めてみたくなるのは魅力的です -n フラグはクラスター上で使用可能なコアの合計数に等しくなりますが、ヘッド ノード上のコアの合計数に制限する必要があります。 残りのコアを個別の「エンジン」として追加します。

ipcluster start -n $RESCALE_CORES_PER_NODE --engines=MPI --ip='*'

コントローラーが起動したら、 ipengines ワーカーノード上で開始する必要があります。 これが自動化されている場合、エンジンを開始する前に、コントローラーの正常な起動時にスリープ コマンドまたはある種のコールバックが必要になります。 エンジンは、コントローラを介して渡される情報を使用してコントローラに接続されます。 ipcontroller-engine.json ファイル。 を輸出する主な理由の XNUMX つは、 IPYTHONDIR 変数は、このファイルがデフォルトですべてのノードで使用できるようにするためのものです。

実際にはそれぞれに個別のエンジンを起動する必要があります。   各ワーカーノード上で。 を使用してプロファイルを作成した場合は、 profile create 上で説明したコマンド、 ipcontroller-engine.json ファイルは次の場所にあります ~/work/shared/.ipython/profile_default/security/。 個々のエンジンを開始するには、次のコマンドを使用できます。

ipengine --mpi --file=~/work/shared/.ipython/profile_default/security/ipcontroller-engine.json 

この部分は、すべてのワーカー ノードでエンジンの起動を自動化するようにスクリプト化する必要があります。これを行うスクリプトを以下に示します。 クラスター上のマシン ファイルを取得し、各ワーカー ノードの各コアでエンジンを起動します。

#!/bin/bash headnode=$(head -n 1 $HOME/machinefile)for host in $(cat $HOME/machinefile); もしそうなら! [ "$host" == "$headnode" ]; 次に、for i in $(seq 1 $RESCALE_CORES_PER_NODE); do ssh "$host" "conda activate ~/work/shared/uenv; nohup ipengine --mpi --file=~/work/shared/.ipython/profile_default/security/ipcontroller-engine.json" >> "engine_output.ログ" & スリープ 1 完了 fi 完了

SSH 経由でコマンドを渡す場合でも、「共有」仮想環境をアクティブにすることが重要です。 の追加 nohup コマンドを使用すると、プロセスをリモートでバックグラウンドで実行できます。

一度 ipcluster が稼働しており、接続は比較的簡単です。 以下は、接続していくつかの基本的な操作を実行する方法を示すスニペットです。

from ipyparallel import Clientimport numpy as np # Connect to the default profile rc = Client() # Create a direct view dv = rc[:] # Add 100 sets of 3 numbers in parallel using all engines  dv.map_sync(lambda x, y, z: x + y + z, range(100), range(100), range(100)) # Load balanced view bview = rc.load_balanced_view() # Can be used for jobs that take different amounts of time to complete   bview.map_sync(lambda x: sum(x), np.random.random((10, 100000)))

舞台裏では、多くの機械学習アルゴリズムは信じられないほど並列化可能であり、 GPU これらの並列ワークロードを非常にうまく処理できるため、よく使用されます。 GPU も魅力的で、論理的には XNUMX つの GPU を使用するよりも XNUMX つの GPU を使用する方が簡単です。 (HPC) 数百のコアを持つクラスター。 しかし、Rescaleを使用するとリソースの制約がなくなり、CPUの並列化も可能になります。 これは、一般に CPU 並列化がより良い選択肢であることを示唆しているわけではありません。GPU が多くの場合良い選択肢であることは確かですが、何が可能であるかを知っておくことは役に立ちます。 には多くの機能があります scikit-learn CPU 並列化のサポートが組み込まれているツール セット。 これにより、並列環境が正しく構成されていれば、これらのモデルのスケールアウトが非常に簡単になります。 幸いなことに、上記で概説した手順に従った場合は、数行のコードをうまく挿入し、必要なだけ大きな Rescale クラスターでこれらのモデルの実行を開始できるはずです。 これは次のようになります。

... rc = Client() bview = rc.load_balance_view() register_Parallel_backend('ipyParallel', ラムダ: IPythonParallelBackend(view=bview)) withParallel_backend('ipyParallel'): search.fit(digits.data, Digits.target) ...

サポート ベクター分類 (SVC) アルゴリズムを古典的な MNIST の例に適用した例。計算集約的な部分の大部分は、 ipcluster 以下に示します。

from sklearn.externals.joblib import Parallel, parallel_backend, register_parallel_backend
from sklearn.model_selection import RandomizedSearchCV
from sklearn.datasets import load_digits
from sklearn.svm import SVC
import numpy as np
from ipyparallel import Client
from ipyparallel.joblib import IPythonParallelBackend 

digits = load_digits() 

rc = Client()
bview = rc.load_balanced_view()
register_parallel_backend('ipyparallel', lambda: IPythonParallelBackend(view=bview)) 
param_space = {     
'C': np.logspace(-6, 6, 300),     
'gamma': np.logspace(-8, 8, 300),     
'tol': np.logspace(-4, -1, 300),     
'class_weight': [None, 'balanced'], 
} 

model = SVC(kernel='rbf')
search = RandomizedSearchCV(model, param_space, cv=10, n_iter=1000, verbose=1, n_jobs=-1)

with parallel_backend('ipyparallel'):    
search.fit(digits.data, digits.target)  
  
rc.shutdown()

この問題の場合、フィット時間は、使用される CPU の数に応じて信じられないほどよく調整されます。 ipcluster 複数のノードにまたがる場合でも。

コア数フィットするまでの時間
4コア27.4分
9コア11.7分
18コア6.0分
36コア*3.1分

*複数のノードで実行

スクリプトを作成することをお勧めします ipcluster セットアッププロセスを実行してから、Python スクリプトを個別に呼び出します。 以下にリンクされているジョブの例には、プロセス全体がスクリプト化されている例が含まれています。



mpi4py を使用して初歩的な MPI 呼び出しを Python スクリプトに追加する

Rescale で大規模なクラスターを起動する機能を活用するもう XNUMX つの方法は、次の関数を使用して Python コードを構築することです。 mpi4py。 これには、最初からこれらの呼び出しを使用してコードを構築する必要があります。 これは、プラグ アンド プレイ タイプのソリューションというよりも、 ipcluster、ただし、特定のシナリオでは良いオプションになる可能性があります。 繰り返しますが、複数のノードを持つクラスターで使用する場合は、Conda 環境のクローン作成の手順に従う必要があります。 こちらをご覧ください。.

from mpi4py import MPI import numpy as np comm = MPI.COMM_WORLD Rank = comm.Get_rank() # ポイントツーポイント通信 if Rank == 0: data = np.arange(1000, dtype='i') comm.Send ([データ, MPI.INT], dest=1, タグ=77) elif ランク == 1: データ = np.empty(1000, dtype='i') comm.Recv([データ, MPI.INT], ソース=0, tag=77) # MPI ブロードキャスト if ランク == 0: data = np.arange(100, dtype='i') else: data = np.empty(100, dtype='i') comm.Bcast( data, root=0) for i in range(100):assert data[i] == i # NumPy 配列による集団 I/O amode = MPI.MODE_WRONLY|MPI.MODE_CREATE fh = MPI.File.Open(comm, " ./datafile.contig", amode) バッファ = np.empty(10, dtype=np.int) バッファ[:] = comm.Get_rank() offset = comm.Get_rank()*buffer.nbytes fh.Write_at_all(offset,バッファ) fh.Close()

ここでは基本的な例のみを紹介しますが、詳細については次のサイトを参照してください。 mpi4py ドキュメントと基本的なチュートリアル

スクリプトを実行するには、 mpirun or mpiexec このように呼び出します:

mpiexec -n 4 python script_with_mpi4py.py