scipy.weave.inline が、すべてのノードに共通のホーム ディレクトリを持つクラスターで実行される大規模な並列 MPI 対応アプリケーション内で呼び出される場合、すべてのインスタンスはコンパイル済みコードの同じカタログにアクセスします: $HOME/.pythonxx_compiled。これは明らかな理由から悪いことであり、多くのエラー メッセージが表示されます。この問題はどのように回避できますか?
3 に答える
この問題に関する私の以前の考え:
カタログへのアクセスをシリアル化するには、scipy.weave.catalog を適切なロック メカニズムで強化するか、すべてのインスタンスが独自のカタログを使用する必要があります。
私は後者を選びました。関数は、モジュールのscipy.weave.inline
モジュール レベル名function_catalog
にバインドされているカタログを使用しscipy.weave.inline
ます。これは、このモジュールのコード ( https://github.com/scipy/scipy/tree/v0.12.0/scipy/weave )を調べることで発見できます。
単純な解決策は、プログラムの冒頭でこの名前を別のものにモンキーパッチすることです:
from mpi4py import MPI
import numpy as np
import scipy.weave.inline_tools
import scipy.weave.catalog
import os
import os.path
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
catalog_dir = os.path.join(some_path, 'rank'+str(rank))
try:
os.makedirs(catalog_dir)
except OSError:
pass
#monkeypatching the catalog
scipy.weave.inline_tools.function_catalog = scipy.weave.catalog.catalog(catalog_dir)
スムーズに動作するようになりましinline
た。各インスタンスには、共通の NFS ディレクトリ内に独自のカタログがあります。もちろん、2 つの別個の並列タスクが同時に実行された場合、この命名スキームは壊れますが、これは、カタログが /tmp にある場合にも当てはまります。
編集:上記のコメントで述べたように、複数の独立したジョブが並行して実行される場合、この手順にはまだ問題があります。これは、ランダムな uuid をパス名に追加することで解決できます。
import uuid
u = None
if rank == 0:
u = str(uuid.uuid4())
u = comm.scatter([u]*size, root=0)
catalog_dir = os.path.join('/tmp/<username>/pythoncompiled', u+'-'+str(rank))
os.makedirs(catalog_dir)
#monkeypatching the catalog
scipy.weave.inline_tools.function_catalog = scipy.weave.catalog.catalog(catalog_dir)
もちろん、計算後にこれらのファイルを削除するとよいでしょう:
shutil.rmtree(catalog_dir)
編集:いくつかの追加の問題がありました。cpp ファイルと o ファイルが格納されている中間ディレクトリも、異なるインスタンスからの同時アクセスによる問題が発生するため、上記の方法をこのディレクトリに拡張する必要があります。
basetmp = some_path
catalog_dir = os.path.join(basetmp, 'pythoncompiled', u+'-'+str(rank))
intermediate_dir = os.path.join(basetmp, 'pythonintermediate', u+'-'+str(rank))
os.makedirs(catalog_dir, mode=0o700)
os.makedirs(intermediate_dir, mode=0o700)
#monkeypatching the catalog and intermediate_dir
scipy.weave.inline_tools.function_catalog = scipy.weave.catalog.catalog(catalog_dir)
scipy.weave.catalog.intermediate_dir = lambda: intermediate_dir
#... calculations here ...
shutil.rmtree(catalog_dir)
shutil.rmtree(intermediate_dir)