ABCIでできる簡単マルチGPU実行
AnyTech 木村
1(１) マルチGPUのメリット／デメリット

メリット- 処理の高速化- 理想的には、処理にかかる時間が、「1／GPU数」になる

デメリット- プログラムが複雑化してしまう- 下手をすれば、その実装に、恩恵以上の時間を要してしまう2

(１) マルチGPUのメリット／デメリット

メリット- 処理の高速化- 理想的には、処理にかかる時間が、「1／GPU数」になる

デメリット- プログラムが複雑化してしまう- 下手をすれば、その実装に、恩恵以上の時間を要してしまう

極力簡単に、マルチGPUによる高速化を、ABCI上で実現する方法を、紹介させて頂きます3

(２) ABCIのマルチGPUノード

引用：https://abci.ai/ja/how_to_use/tariffs.html

4

(２) ABCIのマルチGPUノード- Tesla V100 × 4- メモリ容量計：16GB x 4 = 64GB
- メモリ共有可能- Tesla A100 × 8- メモリ容量計：40GB x 8 = 320GB- メモリ共有可能

引用：https://abci.ai/ja/how_to_use/tariffs.html

5

(３) notebookのアサインコマンド例

rt_F(V100x4)

qrsh -l rt_F=1 -g xxxXXXXX -l h_rt=12:00:00
module load gcc/11.2.0
module load python/3.8/3.8.13
module load cuda/11.3/11.3.1
source venv38/bin/activate
jupyter notebook --ip=`hostname` --port=8888 --no-browser

rt_AF(A100x8)

qrsh -l rt_AF=1 -g xxxXXXXX -l h_rt=12:00:00
module load python/3.8/3.8.13
module load cuda/11.5/11.5.2
source venv38a/bin/activate
jupyter notebook --ip=`hostname` --port=8888 --no-browser

参考：https://docs.abci.ai/ja/tips/jupyter-notebook/6

(４) yolov5の学習でマルチGPU
rt_G.small(V100x1)

python train.py --img 640 --batch 16 --epochs 20 \--data data/hoge.yaml --weights yolov5s.pt

rt_F(V100x4)

python -m torch.distributed.run --nproc_per_node 4 \train.py --img 640 --batch 64 --epochs 20 \--data data/hoge.yaml --weights yolov5s.pt \--device 0,1,2,3

rt_AF(A100x8)

python -m torch.distributed.run --nproc_per_node 8 \train.py --img 640 --batch 320 --epochs 20 \--data data/hoge.yaml --weights yolov5s.pt \--device 0,1,2,3,4,5,6,7

参考：https://github.com/ultralytics/yolov5/issues/4757

(５) pytorchにて、カスタムモデルの学習でマルチGPU
rt_G.small(V100x1)

model = hogenet()model.load_state_dict(torch.load(PATH))
model = hogenet()model.load_state_dict(torch.load(PATH))

rt_AF(A100x8)

from sync_batchnorm import convert_model,
DataParallelWithCallback
model = convert_model(model)
model = DataParallelWithCallback(model,device_ids=[0, 1, 2, 3, 4, 5, 6, 7])

参考：https://github.com/vacancy/Synchronized-BatchNorm-PyTorch8

(５) pytorchにて、カスタムモデルの学習でマルチGPU※save時だけ注意

通常の
save

torch.save(model.state_dict(), PATH)

convertmodelでのsavetorch.save(model.module.state_dict(), PATH)

参考：https://qiita.com/conta_/items/c3e173e891145e87e668#解決策1-保存する前に気をつける

9

(６) 推論処理をマルチGPUで実践
データ量

処理対象データ10(６) 推論処理をマルチGPUで実践@rt_G.small (V100x1)

処理対象データ

GPU：011

(６) 推論処理をマルチGPUで実践@rt_F (V100x4)

処理対象データA

GPU：0

処理対象データB

処理対象データC処理対象データD

GPU：1

GPU：2

GPU：3

12

(６) 推論処理をマルチGPUで実践@rt_AF (A100x8)
処理対象 処理対象 処理対象 処理対象 処理対象 処理対象 処理対象 処理対象
データF データG データH
データE
データA データB データC データD

GPU：0

GPU：1

GPU：2

GPU：3

GPU：4

GPU：5

GPU：6

GPU：7

13

(６) 推論処理をマルチGPUで実践
notebookをコピーすると、「-CopyX.ipynb」という名称でインクリメントされる

hoge.ipynb

hoge-Copy1.ipynb

hoge-Copy2.ipynb

hoge-Copy3.ipynb

hoge-Copy4.ipynb…
14

(６) 推論処理をマルチGPUで実践コピーしたnotebookを、ブラウザタブにて横展開して、一斉に実行

15

(６) 推論処理をマルチGPUで実践%%javascript
IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')

i_notebook = int(nb_name.split('-Copy')[-1].replace('.ipynb', '')) - 1

import osos.environ["CUDA_VISIBLE_DEVICES"]="%d" % i_notebook
import numpy as np
i_file_from = int(np.ceil(len(filename_list) / 8) * i_notebook)i_file_to = int(np.ceil(len(filename_list) / 8) * (i_notebook + 1))
for filename in filename_list[i_file_from:i_file_to]:…

(６) 推論処理をマルチGPUで実践%%javascript
IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')

- -処理中のnotebook名称が、nb_nameにi_notebook = int(nb_name.split('-Copy')[-1].replace('.ipynb', ''))
1格納される( nb_name = hoge-Copy1.ipynb )import os- waitがかかると失敗しやすい為、
os.environ["CUDA_VISIBLE_DEVICES"]="%d" % i_notebook
冒頭で処理すると良い
import numpy as np
i_file_from = int(np.ceil(len(filename_list) / 8) * i_notebook)i_file_to = int(np.ceil(len(filename_list) / 8) * (i_notebook + 1))
for filename in filename_list[i_file_from:i_file_to]:…

(６) 推論処理をマルチGPUで実践%%javascriptIPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')

i_notebook = int(nb_name.split('-Copy')[-1].replace('.ipynb', '')) - 1

import osos.environ["CUDA_VISIBLE_DEVICES"]="%d"-%「hoge-Copy1.ipynb」から、i_notebook「1.ipynb」を切出す
import numpy as np
i_file_from = int(np.ceil(len(filename_list) / 8) * i_notebook)i_file_to = int(np.ceil(len(filename_list) / 8) * (i_notebook + 1))
for filename in filename_list[i_file_from:i_file_to]:…

(６) 推論処理をマルチGPUで実践%%javascript
IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')

i_notebook = int(nb_name.split('-Copy')[-1].replace('.ipynb', '')) - 1

import osos.environ["CUDA_VISIBLE_DEVICES"]="%d" % i_notebook
import numpy as np
i_file_from = int(np.ceil(len(filename_list) / 8) * i_notebook)i_file_to = int(np.ceil(len(filename_list) / 8) * (i_notebook + 1))
for filename in filename_list[i_file_from:i_file_to]:…

- 「1.ipynb」から「1」を切出す

(６) 推論処理をマルチGPUで実践%%javascript
IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')

i_notebook = int(nb_name.split('-Copy')[-1].replace('.ipynb', '')) - 1

import osos.environ["CUDA_VISIBLE_DEVICES"]="%d" % i_notebook- 文字列を整数型にキャストする

import numpy as np
i_file_from = int(np.ceil(len(filename_list) / 8) * i_notebook)i_file_to = int(np.ceil(len(filename_list) / 8) * (i_notebook + 1))
for filename in filename_list[i_file_from:i_file_to]:…

(６) 推論処理をマルチGPUで実践%%javascript
IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')

i_notebook = int(nb_name.split('-Copy')[-1].replace('.ipynb', '')) - 1

import osos.environ["CUDA_VISIBLE_DEVICES"]="%d"% i_notebook- pythonは、zeroオリジンの言語である為、「Copy1」が「0」となるように調整
import numpy as np
i_file_from = int(np.ceil(len(filename_list) / 8) * i_notebook)i_file_to = int(np.ceil(len(filename_list) / 8) * (i_notebook + 1))
for filename in filename_list[i_file_from:i_file_to]:…

(６) 推論処理をマルチGPUで実践%%javascript
IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')

i_notebook = int(nb_name.split('-Copy')[-1].replace('.ipynb', '')) - 1

import osos.environ["CUDA_VISIBLE_DEVICES"]="%d" % i_notebook
import numpy as np
i_file_from = int(np.ceil(len(filename_list) / 8) * i_notebook)i_file_to = int(np.ceil(len(filename_list) / 8) * (i_notebook + 1))- 「CopyX.ipynb」という名称に対応する

GPUをアサインする

for filename in filename_list[i_file_from:i_file_to]:…

(６) 推論処理をマルチGPUで実践%%javascript
IPython.notebook.kernel.execute('nb_name = "' + IPython.notebook.notebook_name + '"')

- データ分割は、ファイル名称で分けるなり、個別
i_notebook = int(nb_name.split('-Copy')[-1].replace('.ipynb','')) - 1にアジャストすればOK- 出力先が共通になってしまわないように、注意をする必要はあり
import osos.environ["CUDA_VISIBLE_DEVICES"]="%d" % i_notebook
import numpy as np
i_file_from = int(np.ceil(len(filename_list) / 4) * i_notebook)i_file_to = int(np.ceil(len(filename_list) / 4) * (i_notebook + 1))
for filename in filename_list[i_file_from:i_file_to]:…

(６) 推論処理をマルチGPUで実践コピーしたnotebookを、ブラウザタブにて横展開して、一斉に実行

24

25