やること

互いにssh接続できるマシンをipyparallelでクラスタ化する。
ルート権限はない。
とりあえず1ノードをマスター(jupyter notebook サーバとipyparallelコントローラ)、
全ノードがスレーブ(ipyparallelエンジン)になるように設定する。
作業は全部マスターノード上でok。

環境

Ubuntu 14.04
    • host1, host2, host3, host4

 

    • それぞれパスワードなし公開鍵でログイン可能

 

    • /home 以下はNFSをマウント

 

    全部ユーザ名はuser
Anaconda
$ conda --version
conda 4.4.6
$ which python
/home/user/anaconda3/bin/python
$ python --version
Python 3.6.3 :: Anaconda custom (64-bit)
jupyter
$ jupyter --version
4.3.0
ipyparallel
$ python -c "import ipyparallel; print(ipyparallel.__version__)"
6.0.2

インストール

$ conda install ipyparallel

設定

Jupyterでの IPython Clusters tab の有効化

$ ipcluster nbextension enable --user

–userをつけないとよくわからないパスのjupyterを探してしまう。

クラスタ用のprofile, kernelspec の設定

ipyparallelはipythonのprofile単位で設定を保存するが
その設定をjupyter上で切り替えられるように。

プロファイル作成
$ ipython profile create --parallel --name=parallel
kernelspec作成
$ jupyter kernelspec install --user --name=parallel
kernelspec確認
$ jupyter kernelspec list
Available kernels:
  parallel    /home/user/.local/share/jupyter/kernels/parallel
  python3     /home/user/anaconda3/share/jupyter/kernels/python3

もしかしたらkernelspec作成で–userいらないかも。

作成したkernelspecでのipython profileを設定
{
 "argv": [
  "/home/user/anaconda3/bin/python",
  "-m",
  "ipykernel_launcher",
  "-f",
  "{connection_file}",
  "--profile",
  "parallel"
 ],
 "display_name": "parallel",
 "language": "python"
}

“–profile”, “parallel”を追加した。

ipyparallelの設定ファイルの編集

# SSHでエンジン(ノード)を起動
c.IPClusterEngines.engine_launcher_class = 'SSH'
# NFSなのでファイルの同期はしない
c.SSHLauncher.to_fetch = []
c.SSHLauncher.to_send = []
c.SSHEngineSetLauncher.engines = {               
    host:{
        # 各ノードで一つずつカーネルを起動
        'n':1,
     # パスの設定はログイン時にしかしていないのでここで絶対パスで指定
        'engine_cmd':['/home/user/anaconda3/bin/python',
                          '-m', 'ipyparallel.engine']}
    for host in ['host1', 'host2', 'host3', 'host4']
}
# 詳しいことはめんどいのでセキュリティガン無視で全部許可
c.RegistrationFactory.ip = '*'
c.HubFactory.client_ip = '*'
c.HubFactory.engine_ip = '*'
c.HubFactory.monitor_ip = '*'

起動

$ ipcluster start --profile=parallel

各ノードでエンジンが起動していないときは–debugフラグをつけると色々情報が出る。
これで無事起動するならjupyterのipython clustersタブでも起動できるようになる。

確認

import ipyparallel as ipp
c = ipp.Client()
print(c.ids)
def test():
    import os, socket
    return os.getcwd(), socket.gethostname()
print(c[:].apply_sync(test))

ちゃんと実行できてホスト名が出てくればok。
実行すればわかるけどワーキングディレクトリは同期されないから注意がいる。

追記

AsyncResultオブジェクトに対するautocomplete (TAB)はデフォルトだとカーネルが停止する。
次の設定をnotebookの先頭に書いておくと解決した。
詳しいことは時間ある時にでも。。。

%config Completer.use_jedi = False

追記その2

シェルコマンドのバカパラ実行例
https://gist.github.com/emakryo/c00e8484c0844fa646ca9fea8350d2cb

追記その3

autoreload が部分的にしか動かない

import bar
def foo_func():
    return bar.bar_func()
def bar_func():
    return 10

でbar_funcをいじって再び実行すると
ローカルではfoo_funcもbar_funcも正しく実行されるが
クラスタ上ではbar_funcしか正しく実行されない。
sync_importを使った場合でも一緒。

workaroundとしてはipclusterを再起動すればとりあえず動きはするが
いちいち再起動するのはめんどくさい。

追記その4

モジュールのリロードはimportlib.reloadを使えばできる。

def reload(mod_names):
    import sys
    from importlib import reload
    for m in mod_names:
        if m in sys.modules:
            reload(sys.modules[m])

c = ipp.Client()
c[:].apply_sync(reload, ['my_module'])

参照

http://ipyparallel.readthedocs.io/en/stable/process.html (ipyparallel設定)

http://jupyter.readthedocs.io/en/latest/migrating.html (kernelspecとprofileについて)

https://qiita.com/tomochiii/items/8b937f15c79a0c3eae0e (kernelspec)

广告
将在 10 秒后关闭
bannerAds