Contenu connexe Similaire à [db analytics showcase Sapporo 2017] A15: Pythonでの分散処理再入門 by 株式会社HPCソリューションズ 飯坂剛一 (20) Plus de Insight Technology, Inc. (20) [db analytics showcase Sapporo 2017] A15: Pythonでの分散処理再入門 by 株式会社HPCソリューションズ 飯坂剛一 4. About me
• 飯坂 剛一 (いいさか ごういち)
– (株) HPCソリューションズ
– go.iisaka@hpc-sol.co.jp / iisaka51@gmail.com
– 普段は...役務やコンサルタントをしています。
• クラスタシステムの導入や構築
• Deep Learning プラットフォームの導入や構築
• Open Source の導入と活用方法のコンサルティング
– 好きな言語: Python
11. 為替取引でのデータ
• 通貨ペアごとのデータを保持
– USDJPY, EURUSD, EURJPY, GBPUSD, GBPJPY...
• 各時間単位での売値(Bit), 買値(Ask)の時系列データ
– 1M, 1D, 4H, 1H, 30M, 15M, 5M, 1M, Tick
• 各時間単位での売買ボリュームの時系列データ
15. Python / Jupyter notebook のカバー領域
探索と分析
プロジェクトでnotebookのようなアプリや
Pythonを活用する
コラボレーションと公開
共有ノートブックやプロジェクトの集中管理、
エンタープライズ認証による安全な管理
ディプロイと運用
並列フレームワークとリソース管理の統合
アナリスト データサイエンティスト 開発者 データエンジニア DevOps
https://www.continuum.io/anaconda-enterprise-notebooks
16. Conda
• Python 3.6 が使える (Python 2.x, Python 3.x)
• x86_64, PowerPC, ARMv7 サポート
– Raspbery Pi2 でも動作する
17. Anaconda と Miniconda
• Miniconda は Anaconda のサブセット
• 後からパッケージは追加できるので Miniconda でOK
– 異なるバージョンの Python も追加できる
• 2つのバージョン
– Anaconda2 / Miniconda2 - Python 2.7
– Anaconda3 / Miniconda3 - Python 3.6
• Python 2.7 は 2020/01/01 でサポート終了
– https://www.python.org/dev/peps/pep-0373/
19. SMP と Cluster
• SMP (Symmetric Multiprocessing)
– メモリ共有型並列コンピューティング
– 現在はほぼすべてのサーバ、PC、スマートフォンがSMP
– 処理はひとつのノード内だけで実行される
• Cluster
– 複数のコンピュータをネットワークで結合した並列コンピューティング
– 冗長化クラスタ(HAクラスタ)と区別するために
BeoWulf型クラスタやHPCクラスタと呼ばれることもある
– 処理は複数のノードで実行される
29. gevent と tornado の比較
• グリーンスレッド
– スレッドはハードウェアではなくアプリケーションレベルで制御される
– スレッドのようにみえるが、CPUのコンテキストスイッチは起きない
– 通常のスレッドプログラミングの問題点はのこる
• コールバック
– スレッドプログラミングとは同じようには書けない
– スレッド/コルーチンはプラグラマには隠蔽される
– 例外は飲み込まれて伝わってこない
– コールバックの結果を集められない
41. コレクション
• Array - NumPy の array と同じインタフェース
• DataFrame - Pandas の DataFrame と同じインタフェース
• Bag - Python オブジェクトを格納
• Delayed - 遅延評価
42. Array
import numpy as np
f = h5py.File('myfile.hdf5')
x = np.array(f['/small-data'])
x - x.mean(axis=1)
import dask.array as da
f = h5py.File('myfile.hdf5')
x = da.from_array(f['/big-data'], chunks=(1000, 1000))
x - x.mean(axis=1).compute()
• NumPyと同じように使える
43. DataFrame
import pandas as pd
dd.read_csv('2015-*-*.csv')
df.groupby(df.user_id).value.mean()
import dask.dataframe as dd
df = dd.read_csv('2015-*-*.csv')
df.groupby(df.user_id).value.mean().compute()
• Pandas と同じように使える
46. クラスタの作成
• 準備: 各ノードで distibuted のインストール
$ conda create -y -n demo
$ source activate demo
(demo) $ conda install bokeh
(demo) $ conda install distributed
47. スケジューラの起動
(demo) $ dask-schudler
dask-scheduler
distributed.scheduler - INFO - -----------------------------------------------
distributed.scheduler - INFO - Scheduler at: 159.203.166.31:8786
distributed.scheduler - INFO - http at: 159.203.166.31:9786
distributed.scheduler - INFO - bokeh at: 159.203.166.31:8788
distributed.bokeh.application - INFO - Web UI: http://159.203.166.31:8787/status/
distributed.scheduler - INFO - -----------------------------------------------
distributed.scheduler - INFO - Receive client connection: 20d2354a-dd86-11e6-9fe3-
a634b264672b
48. ワーカーの起動
• スケジューラの"ホスト:ポート"を引数として与える
(demo) $ dask-worker 159.203.166.31:8786 --memory-limit=auto
distributed.nanny - INFO - Start Nanny at: 138.197.11.22:36452
distributed.worker - INFO - Start worker at: 138.197.11.22:39702
distributed.worker - INFO - nanny at: 138.197.11.22:36452
distributed.worker - INFO - http at: 138.197.11.22:34241
distributed.worker - INFO - bokeh at: 138.197.11.22:8789
distributed.worker - INFO - Waiting to connect to: 159.203.166.31:8786
distributed.worker - INFO - -------------------------------------------------
distributed.worker - INFO - Threads: 2
distributed.worker - INFO - Memory: 2.49 GB
distributed.worker - INFO - Local Directory: /tmp/nanny-xk59hltv
distributed.worker - INFO - -------------------------------------------------
50. クラスタの作成 (Python API)
• プログラムの中からスケジューラを起動
from distributed import Scheduler
from tornado.ioloop import IOLoop
from threading import Thread
loop = IOLoop.current()
t = Thread(target=loop.start, daemon=True)
t.start()
s = Scheduler(loop=loop)
s.start('tcp://:8786')
51. クラスタの作成 (Python API)
• プログラムの中からワーカーを起動
from distributed import Worker
from tornado.ioloop import IOLoop
from threading import Thread
loop = IOLoop.current()
t = Thread(target=loop.start, daemon=True)
t.start()
w = Worker('tcp://159.203.166.31:8786', loop=loop)
w.start()
52. タスクの実行
• スケジューラの"ホスト:ポート"を与える
from dask.distributed import Client
client = Client('159.203.166.31:8786')
data = [client.submit(load, fn) for fn in filenames]
processed = [client.submit(process, d, resources={'GPU': 1}) for d in data]
final = client.submit(aggregate, processed, resources={'MEMORY': 70e9})
60. mpi4py: Hello World in Python
#!/usr/bin/env python
from mpi4py import MPI
import sys
size = MPI.COMM_WORLD.Get_size() # SPMD環境の規模を取得
rank = MPI.COMM_WORLD.Get_rank() # このプロセスのランク(番号)
name = MPI.Get_processor_name() # このプロセスのプロセス名
sys.stdout.write(
"Hello, World! I am process %d of %d on %s.n"
% (rank, size, name))
61. Hello World 実行方法
$ mpicc -o helloworld.exe helloworld.c
$ mpiexec -n 4 helloworld.exe
プロセス数の指定
$ mpiexec -n 4 python helloworld.py
62. conda を使うときは...
• システム側の python と混乱しやすい
• module コマンドで環境をロードするようにするとよい
– http://modules.sourceforge.net/
– 例: module load conda
• conda 環境を作っていればアクティベートを忘れやすい
– 例: source activate demo
69. 画像処理: ノイズ除去シリアル版
import numpy as np
from skimage import data, img_as_float
from skimage.filter import denoise_bilateral
import skimage.io
import os.path
import time
curPath = os.path.abspath(os.path.curdir)
noisyDir = os.path.join(curPath,'noisy')
denoisedDir = os.path.join(curPath,'denoised')
70. 画像処理: ノイズ除去シリアル版 (続き)
def loop(imgFiles):
for f in imgFiles:
img = img_as_float(data.load(os.path.join(noisyDir,f)))
startTime = time.time()
img = denoise_bilateral(img, sigma_range=0.1, sigma_spatial=3),
skimage.io.imsave(os.path.join(denoisedDir,f), img)
print("Took %f seconds for %s" %(time.time() - startTime, f))
def serial():
total_start_time = time.time()
imgFiles = ["%.4d.jpg"%x for x in range(1,101)]
loop(imgFiles)
print("Total time %f seconds" %(time.time() - total_start_time))
if __name__=='__main__':
serial()
72. 画像処理: ノイズ除去MPI版 (続き)
def loop(imgFiles,rank):
for f in imgFiles:
img = img_as_float(data.load(os.path.join(noisyDir,f)))
startTime = time.time()
img = denoise_bilateral(img, sigma_range=0.1, sigma_spatial=3),
skimage.io.imsave(os.path.join(denoisedDir,f), img)
print ("Process %d: Took %f seconds for %s" % (
rank, time.time() - startTime, f))
78. 通常のMPIでのデータ送受信
• ホスト上のメモリへのポインタのみがMPIに渡される。
• cudaMemcpyを使用してGPUバッファをホストメモリ経由で
ステージングする必要がある。
//MPI rank 0
cudaMemcpy(s_buf_h,s_buf_d,size,cudaMemcpyDeviceToHost);
MPI_Send(s_buf_h,size,MPI_CHAR,1,100,MPI_COMM_WORLD);
//MPI rank 1
MPI_Recv(r_buf_h,size,MPI_CHAR,0,100,MPI_COMM_WORLD, &status);
cudaMemcpy(r_buf_d,r_buf_h,size,cudaMemcpyHostToDevice);
79. CuDA-aware MPIでのデータ送受信
• CuDA-aware MPIでは cudaMemcpy() が不要。
//MPI rank 0
MPI_Send(s_buf_d,size,MPI_CHAR,1,100,MPI_COMM_WORLD);
//MPI rank n-1
MPI_Recv(r_buf_d,size,MPI_CHAR,0,100,MPI_COMM_WORLD, &status);
86. CUDA-aware MPI / GPUDirect P2P
GPUメモリ GPUメモリ
Host Buffer Host Buffer
• 同じシステム内の2つのGPUのメモリ間では直接コピーする
87. CUDA-aware MPI / GPUDirect RDMA
GPUメモリ GPUメモリ
Host Buffer Host Buffer
• 他ノードのGPUのメモリ間ではホストのメモリを経由せずにコピー
91. HPCS-DLD
• Anaconda Python をベースにDeepLearningの
フレームワークやライブラリ、ミドルウェアをパッケージングした
ソフトウェアディストリビューション
• それぞれのオープンソース・ライセンスに準じて無償で
使用することができます。
– http://www.hpc-sol.co.jp/dld/
• サブスクリプション契約をするとアップディトレポジトリへのアクセスと
アップディトリクエストが可能になります。
93. 参考資料
• Anaconda Python
– https://www.continuum.io/
• NumPy
– http://www.numpy.org/
• SciPy
– https://www.scipy.org/
• Blaze
– http://blaze.pydata.org/
• Statsmodules
– http://www.statsmodels.org/stable/index.html
• Pandas
– http://pandas.pydata.org/
• Blaze
– http://blaze.pydata.org/
• HDF5
– https://support.hdfgroup.org/HDF5/
• matplotlib
– https://matplotlib.org/
• seaborn
– https://seaborn.pydata.org/
• Jupyter
– http://jupyter.org/
• Orange
– https://orange.biolab.si/
• dispy
– http://dispy.sourceforge.net/
• Parallel Python
– http://www.parallelpython.com/
• mpi4py
– http://pythonhosted.org/mpi4py/
• OpenMPI
– https://www.open-mpi.org/
94. 参考資料
• Calculations with arrays bigger than your memory (Dask arrays)
– http://earthpy.org/dask.html
• mpi4py-examplpes
– https://github.com/jbornschein/mpi4py-examples
• Grok The GIL: How to write fast and thread-safe Python
– https://opensource.com/article/17/4/grok-gil
• Python 3.5 で実装された async/await を使って軽量スレッドの性能ベンチマーク
– http://qiita.com/haminiku/items/0aaf87e9a52ed41b60a7
• Python における非同期処理: asyncio逆引きリファレンス
– http://qiita.com/icoxfog417/items/07cbf5110ca82629aca0
• Asynchronous Python
– https://hackernoon.com/asynchronous-python-45df84b82434
• THe Open Source Data Science Masters
– http://datasciencemasters.org/
• Distributed parallel programming in Python : MPI4PY
– https://www.howtoforge.com/tutorial/distributed-parallel-programming-python-mpi4py/
• Awesome Python
– https://awesome-python.com/