EDIT(2018/05/26): ChainerMN 1.2.0/13.0 において実装された double buffering および FP16 サポートの機能により AWS 環境でも高い分散効率を出せるようになったようです。See ChainerMNのクラウド環境向け新機能とAWSにおける性能評価 | Preferred Research
AWS EC2 インスタンスにおける ChainerMN の分散効率に対する評価を実施した。ChainerMN のバージョンは 1.0.0。
AWS の p3 (v100) インスタンスもつい最近ローンチされたので、p2 と p3 インスタンスで評価を実施する。
バージョンなど
- AWS p2 (k80) および p3 (v100) インスタンス
- Ubuntu 16.04
- Python 3.5.2 (
/usr/bin/python3
of Ubuntu 16.04) - CUDA 9.0
- cuDNN 7.0.3
- Chainer 4.0.0a1
- CuPy 3.0.0a1
- Open MPI v3.0.0
- ChainerMN 1.0.0
実行したコマンド
hostfile を用意して、chainermn にある mnist, reset50 examples を利用
mpiexec --hostfile hostfile python3 chainermn/examples/mnist/train_mnist.py --gpu
mpiexec --hostfile hostfile python3 chainermn/examples/imagenet/train_imagenet.py --arch resnet50 --epoch 100 --batchsize 32 2048 2048
hostfile は例えば p2.8xlarge の場合は、1ホストで8プロセス走らせたいので cpu=8
と指定する。
host01 cpu=8
host02 cpu=8
なお、分散数 * batchsize が総バッチサイズになる
resnet50 へのパッチ
resnet50 に対しては、データを用意するのが面倒だったので、パッチをあててランダムにデータを生成して計測した。精度は全くあてにならなくなるが、分散効率の評価には十分使える。
chainermn/examples/imagenet/train_imagenet.py にあてたパッチ
--- a/examples/imagenet/train_imagenet.py
+++ b/examples/imagenet/train_imagenet.py
@@ -43,16 +43,21 @@ if major <= 2 or (major == 3 and minor < 4):
class PreprocessedDataset(chainer.dataset.DatasetMixin):
- def __init__(self, path, root, mean, crop_size, random=True):
- self.base = chainer.datasets.LabeledImageDataset(path, root)
+ def __init__(self, length, root, mean, crop_size, random=True):
+ # self.base = chainer.datasets.LabeledImageDataset(path, root)
+ self.length = int(length)
self.mean = mean.astype('f')
self.crop_size = crop_size
self.random = random
def __len__(self):
- return len(self.base)
+ return self.length # len(self.base)
def get_example(self, i):
+ image = np.random.rand(3, self.crop_size, self.crop_size).astype('f')
+ label = np.random.randint(0, 9, 1, 'int32')[0]
+ return image, label
+
# It reads the i-th image/label pair and return a preprocessed image.
# It applies following preprocesses:
# - Cropping (random or center rectangular)
@@ -160,7 +165,7 @@ def main():
# Split and distribute the dataset. Only worker 0 loads the whole dataset.
# Datasets of worker 0 are evenly split and distributed to all workers.
- mean = np.load(args.mean)
+ mean = np.random.rand(3, model.insize, model.insize).astype('f') # np.load(args.mean)
if comm.rank == 0:
train = PreprocessedDataset(args.train, args.root, mean, model.insize)
val = PreprocessedDataset(
@@ -175,7 +180,7 @@ def main():
# using InfiniBand and MultiprocessIterator. This is because processes
# often crash when calling fork if they are using Infiniband.
# (c.f., https://www.open-mpi.org/faq/?category=tuning#fork-warning )
- multiprocessing.set_start_method('forkserver')
+ # multiprocessing.set_start_method('forkserver')
train_iter = chainer.iterators.MultiprocessIterator(
train, args.batchsize, n_processes=args.loaderjob)
val_iter = chainer.iterators.MultiprocessIterator(
メトリクス計測方法
速度
実行時に出てくる iters/sec を取得して計測。ChainerMN のメインプロセスでのみ表示されるので、iters/sec/process と捉えて、分散数倍する。
total [######............................................] 13.28%
this epoch [##############....................................] 28.12%
850 iter, 13 epoch / 100 epochs
5.3518 iters/sec. Estimated time to finish: 0:17:17.042087.
GPU Usages
nvidia-smi で取れる。この時に重要なのが、 Volatile GPU-Util
だけではなく、 Persistence-M Pwr:Usage/Cap
も見ること。NCCLによる通信待ちの状態でも GPU-Util は 100% になるので、区別するには使用電力を見る必要がある。
最初は GPU-Util だけ見て「100% 使ってるのに遅いなぁ、おかしい」などと言っていた。要注意。
$ nvidia-smi
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 384.90 Driver Version: 384.90 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 Tesla V100-SXM2... Off | 00000000:00:1E.0 Off | 0 |
| N/A 45C P0 90W / 300W | 4194MiB / 16152MiB | 55% Default |
+-------------------------------+----------------------+----------------------+
CPU Usages
top -c のあと 1 を打って、コアごとの Usages をみること。
network traffic が増えると sys (kernel) に使われる CPU 使用率が上がる傾向が見られた。
$ top -c
%Cpu0 : 36.1 us, 31.8 sy, 0.0 ni, 32.1 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 40.4 us, 1.7 sy, 0.0 ni, 55.7 id, 0.0 wa, 0.0 hi, 1.7 si, 0.3 st
%Cpu2 : 49.8 us, 18.7 sy, 0.0 ni, 31.4 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 68.9 us, 10.7 sy, 0.0 ni, 15.7 id, 0.0 wa, 0.0 hi, 4.3 si, 0.3 st
%Cpu4 : 69.5 us, 0.3 sy, 0.0 ni, 28.9 id, 0.0 wa, 0.0 hi, 1.3 si, 0.0 st
%Cpu5 : 89.1 us, 0.0 sy, 0.0 ni, 10.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu6 : 33.0 us, 20.5 sy, 0.0 ni, 41.7 id, 0.0 wa, 0.0 hi, 4.9 si, 0.0 st
%Cpu7 : 39.3 us, 10.2 sy, 0.0 ni, 49.2 id, 0.0 wa, 0.0 hi, 1.4 si, 0.0 st
Network bandwidth
ChainerMN は現状、計算→通信→計算→通信 という動きをする。このワークロードではバーストトラフィックを見なければならない。
最初は iotop
や ifstat
などで 1s あたりの平均ネットワーク帯域を見ていて、「ネットワーク帯域が余っているのに遅いなぁ、おかしい」などと言っていた。要注意。
以下の python スクリプトで 1ms 辺りのネットワーク帯域を観測した。/proc/net/dev
を 1ms ごとに観測して、ネットワーク帯域を出力している。
ネットワークデバイス(ドライバ)によっては 1ms の解像度で観測できないらしいが、幸いなことに p2.16xlarge よび p3.x16xlarge の環境ではこのスクリプトで 1ms の解像度で観測できた。実際はもっと細かい解像度で観測する必要があると思われるため、この値はあくまで参考値とした。
import re
import time
import os
SLEEP_SEC = 0.001
if os.system('ifconfig eth0 > /dev/null 2>&1') == 0:
INTERFACE = 'eth0'
elif os.system('ifconfig ens3 > /dev/null 2>&1') == 0:
INTERFACE = 'ens3'
else:
raise('interface is not found')
while True:
b_time = time.clock_gettime(time.CLOCK_MONOTONIC)
with open('/proc/net/dev') as f:
b_lines = f.readlines()
time.sleep(SLEEP_SEC)
with open('/proc/net/dev') as f:
a_lines = f.readlines()
a_time = time.clock_gettime(time.CLOCK_MONOTONIC)
for line in b_lines:
if line.find(INTERFACE) >= 0:
b_rx_bytes = int(line.split()[1])
b_tx_bytes = int(line.split()[9])
break
for line in a_lines:
if line.find(INTERFACE) >= 0:
a_rx_bytes = int(line.split()[1])
a_tx_bytes = int(line.split()[9])
break
d_rx_bytes = a_rx_bytes - b_rx_bytes
d_tx_bytes = a_tx_bytes - b_tx_bytes
d_time = a_time - b_time
print("%d bps(in), %d bps(out), %.5f sec" % (d_rx_bytes / d_time * 8, d_tx_bytes / d_time * 8, d_time))
$ python3 net.py | tee /tmp/net.out
3528738 bps(in), 1354050 bps(out), 0.00120 sec
...
...
$ expr $(cat /tmp/net.out | awk '{print $1}' | sort -nr | head -1) / 1024 / 1024 / 1024
14 # Gbps
Disk IO やメモリなど
さっと見た感じ余裕で余っていたので観測は飛ばした。
計測結果
- p2 インスタンスは k80、p3 インスタンスは v100 を装備
- k80 一枚あたり $0.9/h (oregon)、v100 一枚あたり $3.06/h (oregon) でコスト換算できる
Spreadsheet で見たい方はこちら。計測したメトリクスについては Spreadsheet にしか書いてない。
https://docs.google.com/spreadsheets/d/14s1YQpU1x6zmHQOC2wCwQWWez6jw6lQrC4h93dJN6ME/edit?usp=sharing
resnet50
Machine Spec | Result | ||||||
---|---|---|---|---|---|---|---|
Machine type | # of Machines | # of GPUs | Measured Network bandwidth by iperf |
iters/sec/process | Speed-up | Speed-up (vs p2) |
Parallel Efficiency (1 is great) |
p2.xlarge | 1 | 1 | 1.44Gbps | 1.2071 | 1 | 1 | |
2 | 2 | 1.44Gbps | 1.0223 | 1.6938 | 0.847 | ||
3 | 3 | 1.44Gbps | 0.99681 | 2.4774 | 0.8258 | ||
4 | 4 | 1.44Gbps | 0.95933 | 3.179 | 0.7948 | ||
p2.8xlarge | 1 | 8 | 10Gbps | 1.1848 | 7.8522 | 0.9816 | |
2 | 16 | 10Gbps | 0.97573 | 12.9332 | 0.8084 | ||
3 | 24 | 10Gbps | 0.93625 | 18.6149 | 0.7757 | ||
4 | 32 | 10Gbps | 0.90176 | 23.9055 | 0.7471 | ||
p2.16xlarge | 1 | 16 | 24.5Gbps | 1.0875 | 14.4147 | 0.901 | |
2 | 32 | 24.5Gbps | 0.87994 | 23.327 | 0.729 | ||
3 | 48 | 24.5Gbps | 0.79586 | 31.6472 | 0.6594 | ||
4 | 64 | 24.5Gbps | 0.76187 | 40.3941 | 0.6312 | ||
p3.2xlarge | 1 | 1 | 10Gbps | 5.3518 | 1 | 4.4336 | 1 |
2 | 2 | 10Gbps | 2.4848 | 0.9286 | 4.117 | 0.4643 | |
3 | 3 | 10Gbps | 2.1693 | 1.216 | 5.3914 | 0.4054 | |
4 | 4 | 10Gbps | 2.1558 | 1.6113 | 7.1437 | 0.4029 | |
p3.8xlarge | 1 | 4 | 10Gbps | 5.2089 | 3.8932 | 17.2609 | 0.9733 |
2 | 8 | 10Gbps | 3.1953 | 4.7764 | 21.1767 | 0.5971 | |
3 | 12 | 10Gbps | 2.1676 | 4.8603 | 21.5485 | 0.4051 | |
4 | 16 | 10Gbps | 2.587 | 7.7342 | 34.2904 | 0.4834 | |
p3.16xlarge | 1 | 8 | 24.5Gbps | 5.0137 | 7.4946 | 33.2281 | 0.9369 |
2 | 16 | 24.5Gbps | 2.4339 | 7.2765 | 32.2611 | 0.4548 | |
3 | 24 | 24.5Gbps | 2.1206 | 9.5098 | 42.1625 | 0.3963 | |
4 | 32 | 24.5Gbps | 1.9216 | 11.4898 | 50.9413 | 0.3591 |
mnist
Machine Spec | Result | ||||||
---|---|---|---|---|---|---|---|
Machine type | # of Machines | # of GPUs | Measured Network bandwidth by iperf |
Seconds for 1 epoch |
Speed-up | Speed-up (vs p2) |
Parallel Efficiency (1 is great) |
p2.xlarge | 1 | 1 | 1.44Gbps | 5.4 | 1 | 1 | |
2 | 2 | 1.44Gbps | 13.9 | 0.3885 | 0.1942 | ||
4 | 4 | 1.44Gbps | 10.5 | 0.5143 | 0.1286 | ||
8 | 8 | 1.44Gbps | 6.1 | 0.8852 | 0.1107 | ||
p2.8xlarge | 1 | 8 | 10Gbps | 0.72 | 7.5 | 0.9375 | |
2 | 16 | 10Gbps | 0.74 | 7.2973 | 0.4561 | ||
3 | 24 | 10Gbps | 0.65 | 8.3077 | 0.3462 | ||
4 | 32 | 10Gbps | 0.47 | 11.4894 | 0.359 | ||
p2.16xlarge | 1 | 16 | 24.5Gbps | 0.39 | 13.8462 | 0.8654 | |
2 | 32 | 24.5Gbps | 0.46 | 11.7391 | 0.3668 | ||
3 | 48 | 24.5Gbps | 0.39 | 13.8462 | 0.2885 | ||
4 | 64 | 24.5Gbps | 0.31 | 17.4194 | 0.2722 | ||
p3.2xlarge | 1 | 1 | 10Gbps | 4.8 | 1 | 1.125 | 1 |
2 | 2 | 10Gbps | 4.8 | 1 | 1.125 | 0.5 | |
3 | 3 | 10Gbps | 4 | 1.2 | 1.35 | 0.4 | |
4 | 4 | 10Gbps | 3.6 | 1.3333 | 1.5 | 0.3333 | |
p3.8xlarge | 1 | 4 | 10Gbps | 1.24 | 3.871 | 4.3548 | 0.9677 |
2 | 8 | 10Gbps | 1.2 | 4 | 4.5 | 0.5 | |
3 | 12 | 10Gbps | 0.9 | 5.3333 | 6 | 0.4444 | |
4 | 16 | 10Gbps | 0.8 | 6 | 6.75 | 0.375 | |
p3.16xlarge | 1 | 8 | 24.5Gbps | 0.62 | 7.7419 | 8.7097 | 0.9677 |
2 | 16 | 24.5Gbps | 0.66 | 7.2727 | 8.1818 | 0.4839 | |
3 | 24 | 24.5Gbps | 0.6 | 8 | 9 | 0.303 | |
4 | 32 | 24.5Gbps | 0.58 | 8.2759 | 9.3103 | 0.2586 |
考察
分散効率について
resnet50
p2.8xlarge 4台構成で分散効率 75%、p2.16xlarge 4台構成で分散効率 63% というまずまずの結果が出た。p2.8xlarge においては GPU の消費電力も平均して 100% 近く発揮できていた。
しかし、p3.8xlarge および p3.16xlarge になると、消費電力が平均して 80W/300W ほどに落ちてしまった。v100 になり GPU の計算能力が上がった結果、GPU の計算能力が余ってしまったものと思われる。結果として、分散効率も p3.8xlarge で 48%、p3.16xlarge で 35% に落ち込んでしまった。
mnist
p2.16xlarge 4台構成で分散効率 27%、p3.16xlarge 4台構成でも分散効率 25% と低い結果になった。
mnist に関しては、1 GPUの時点でGPUの利用率が50%程度しかなく、分散することによってさらに GPUの計算能力が余ってしまい、良い結果にならなかった。
精度について
分散数を増やすほど、同エポックでの精度は下がる傾向にあるようだ。最終的には精度は同程度に落ち着くというのがChainerMNの主張なので、分散数を増やした時は、エポック数も気持ち多めに指定する必要がありそう。
※ そういう意味で 1 epoch 辺りの速度を比較しても片手落ちではあるのだよなぁ。
補足: これについては、ChainerMN というよりは、巨大バッチサイズでの学習効率の話になるようで、単純にエポック数を増やせば良いという話ではないようだ。Slow-start Learning rate とか warm up とか[1][2][3]。
[1] Priya Goyal, Piotr Dollár, Ross Girshick, Pieter Noordhuis, Lukasz Wesolowski, Aapo Kyrola, Andrew Tulloch, Yangqing Jia, Kaiming He, Accurate, Large Minibatch SGD: Training ImageNet in 1 Hour
[2] Samuel L. Smith, Pieter-Jan Kindermans, Quoc V. Le, Don't Decay the Learning Rate, Increase the Batch Size
[3] Extremely Large Minibatch SGD: Training ResNet-50 on ImageNet in 15 Minutes, Takuya Akiba, Shuji Suzuki, Keisuke Fukuda
p2 vs p3
mnist においては、p2.16xlarge 1台 (k80 16枚) と p3.16xlarge 1台 (v100 8枚)で速度を比較すると、 GPUの枚数が多いせいか p2.16xlarge 1台のほうが 1.7倍速いという結果が出た。さらに p2.16xlarge のほうが1.7倍安い。
resnet50 においては、p2.16xlarge 1台に比べて p3.16xlarge 1台のほうが 5倍 速いという結果が出た。1.7倍高いが5倍速いなら割にあう。これは以前、別件で調べたのであるが、cuDNN が Convolution2D の計算において、少なくとも pascal 以上の世代では、3x3 kernel において、winograd アルゴリズムを使うようになっているためであると思われる。winograd アルゴリズムが使われると Convolution2D の演算において、winograd が使われない k80 に比べて 10 倍ほど高速化される。
p2.16xlarge 1台 (k80 16枚) と p3.16xlarge 1台 (v100 8枚)で分散効率を比較すると、わずかであるが p3.16xlarge のほうが高くなっていた。これは単純に枚数が少ないのと、ひょっとしたら p3 が NVLink を使用しているのが影響しているかもしれない。
まとめ
ChainerMN の論文では、InfiniBand 装備の 4GPU 4台構成で 83.88%、32台構成で 79.16% の分散効率が出ているが、p2.16xlarge および p3.16xlarge ではネットワーク帯域が 25Gbps 程度であるため、そこまでの分散効率は得られなかった。平均としてはネットワーク帯域が余っているので、ネットワーク転送と演算を並列化するなどできれば、AWS環境でもより効率をあげられる可能性はありそう。
ニューラルネットワークのモデルによって、分散効率が高いものや低いものがあることがわかった。例えば resnet50 はある程度分散効率が高いが、mnist は分散させても計算リソースが余ってしまうだけであまり効果がない。また、その resnet50 においても、p2.8xlarge 4台では 74% の分散効率が出ているが、p3.8xlarge 4台では 48% 程度になるなど、最新世代である v100 では計算リソースが余ってしまう。
AWSの費用を考えると、2台に増やして速度が上がらない(分散効率が50%より低い)モデルの場合は、複数台は諦めて1台構成で学習させるのが割が良さそう。それでも、どうしても札束で速度を買いたい場合は、割に合わない事を理解した上で台数を増やしても良いとは思うが。。。。
構成選択フローチャート
- (1) Conv2D を多用している?
- YES: p3.16xlarge を選択
- NO: p2.16xlarge を選択
- (2) 1台構成と2台構成を比較し、2台構成のほうが速度が速い?
- YES: 複数台構成を選択
- NO: 1台構成で我慢しましょう
おまけ: トラブルシューティング
docker0
あとで nvidia-docker を試そうと思って、docker を入れたホストで実験していたところ、Open MPI および NCCL2 が docker が作る docker0 仮想インターフェースを見にいってしまうようで通信エラーになってしまった。
$ mpiexec --hostfile hostfile python3 chainermn/examples/mnist/train_mnist.py --gpu
WARNING: Open MPI accepted a TCP connection from what appears to be a
another Open MPI process but cannot find a corresponding process
entry for that peer.
This attempted connection will be ignored; your MPI job may or may not
continue properly.
とか
$ mpiexec --hostfile hostfile python3 chainermn/examples/mnist/train_mnist.py --gpu
At least one pair of MPI processes are unable to reach each other for
MPI communications. This means that no Open MPI device has indicated
that it can be used to communicate between these processes. This is
an error; Open MPI requires that all MPI processes be able to reach
each other. This error can sometimes be the result of forgetting to
specify the "self" BTL.
Process 1 ([[38512,1],0]) is on host: host01
Process 2 ([[38512,1],1]) is on host: unknown!
BTLs attempted: self
とか。
$ sudo ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:71:5a:8c:a1
inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
ens3 Link encap:Ethernet HWaddr 06:1b:83:2c:ef:8c
inet addr:xx.xx.xx.xx Bcast:xx.xx.xx.xx Mask:255.255.255.128
inet6 addr: xx::xx:xx:xx:xx/64 Scope:Link
docker をアンインストールして、
sudo ip link set dev docker0 down
sudo ip link delete docker0
として docker0 を削除するか、以下のように mpi および nccl が docker0 を見ないように指定することで実行できた。
mpiexec --mca btl_tcp_if_exclude docker0,lo --hostfile hostfile env NCCL_SOCKET_IFNAME=^docker0 python3 chainermn/examples/mnist/train_mnist.py --gpu
(btl_tcp_if_exclude に docker0 だけでなく lo も指定しないといけなかったのが謎い... )
ref. https://www.open-mpi.org/faq/?category=tcp#tcp-selection
ref. http://tabisurubiker.hatenadiary.jp/entry/2017/10/02/092952
環境変数
mpiexec は ssh ホスト名 コマンド
と同様の動きをする。
ログインシェルが起動しないので、/etc/profile
なり /etc/profile.d/*
なり ~/.bash_profile
なりのファイルは読み込まれない。インタラクティブシェルが起動するわけでもないので /etc/bash.bashrc
なり ~/.bashrc
なりのファイルも読み込まれない。(see also man 1 bash)
この場合に環境変数を渡す方法は以下の3つが考えられる。個人的には (2) bash -lc が楽と思っている。
(1) 実行時に env を渡す
mpiexec --hostfile hostfile env FOO=1 python print_rank.py
(2) bash -lc 経由で実行する
-l
オプションをつけて bash をログインシェルとして起動しつつ、コマンドを実行する。/etc/profile
なりが読み込まれる。
mpiexec --hostfile hostfile bash -lc 'python print_rank.py'
(3) ~/.ssh/environment に記述する
sshd の設定で、PermitUserEnvironment を yes にして、その機能が読み込んでくれる .ssh/environment
に環境変数設定を記述する。
-# PermitUserEnvironment=no
+PermitUserEnvironment=yes
$ sudo /etc/init.d/ssh restart
FOO=1
確認
mpiexec --hostfile hostfile env
OpenBLAS blas_thread_init: pthread_create: Resource temporarily unavailable
1台構成でプロセス数を複数にして mpiexec 経由で train_imagenet.py を実行したところ以下のようなエラーが出た。
Traceback (most recent call last):
File "chainermn/examples/imagenet/train_imagenet.py", line 226, in <module>
main()
File "chainermn/examples/imagenet/train_imagenet.py", line 222, in main
trainer.run()
File "/home/anasys/.local/lib/python3.5/site-packages/chainer/training/trainer.py", line 313, in run
six.reraise(*sys.exc_info())
File "/home/anasys/.local/lib/python3.5/site-packages/six.py", line 693, in reraise
raise value
File "/home/anasys/.local/lib/python3.5/site-packages/chainer/training/trainer.py", line 299, in run
update()
File "/home/anasys/.local/lib/python3.5/site-packages/chainer/training/updater.py", line 223, in update
self.update_core()
File "/home/anasys/.local/lib/python3.5/site-packages/chainer/training/updater.py", line 227, in update_core
batch = self._iterators['main'].next()
File "/home/anasys/.local/lib/python3.5/site-packages/chainer/iterators/multiprocess_iterator.py", line 86, in __next__
self._thread = self._prefetch_loop.launch_thread()
File "/home/anasys/.local/lib/python3.5/site-packages/chainer/iterators/multiprocess_iterator.py", line 314, in launch_thread
initargs=(self.dataset, self.mem_size, self.mem_bulk))
File "/usr/lib/python3.5/multiprocessing/context.py", line 118, in Pool
context=self.get_context())
File "/usr/lib/python3.5/multiprocessing/pool.py", line 168, in __init__
self._repopulate_pool()
File "/usr/lib/python3.5/multiprocessing/pool.py", line 233, in _repopulate_pool
w.start()
File "/usr/lib/python3.5/multiprocessing/process.py", line 105, in start
self._popen = self._Popen(self)
File "/usr/lib/python3.5/multiprocessing/context.py", line 281, in _Popen
return Popen(process_obj)
File "/usr/lib/python3.5/multiprocessing/popen_forkserver.py", line 36, in __init__
super().__init__(process_obj)
File "/usr/lib/python3.5/multiprocessing/popen_fork.py", line 20, in __init__
self._launch(process_obj)
File "/usr/lib/python3.5/multiprocessing/popen_forkserver.py", line 55, in _launch
f.write(buf.getbuffer())
BrokenPipeError: [Errno 32] Broken pipe
SystemError: initialization of multiarray raised unreported exception
OpenBLAS blas_thread_init: pthread_create: Resource temporarily unavailable
OpenBLAS blas_thread_init: RLIMIT_NPROC 2950938 current, 2950938 max
OpenBLAS blas_thread_init: pthread_create: Resource temporarily unavailable
OpenBLAS blas_thread_init: RLIMIT_NPROC 2950938 current, 2950938 max
OpenBLAS blas_thread_init: pthread_create: Resource temporarily unavailable
OpenBLAS blas_thread_init: RLIMIT_NPROC 2950938 current, 2950938 max
OpenBLAS blas_thread_init: pthread_create: Resource temporarily unavailable
OpenBLAS blas_thread_init: RLIMIT_NPROC 2950938 current, 2950938 max
OpenBLAS blas_thread_init: pthread_create: Resource temporarily unavailable
OpenBLAS blas_thread_init: RLIMIT_NPROC 2950938 current, 2950938 max
OpenBLAS blas_thread_init: pthread_create: Resource temporarily unavailable
OpenBLAS blas_thread_init: RLIMIT_NPROC 2950938 current, 2950938 max
OpenBLAS blas_thread_init: pthread_create: Resource temporarily unavailable
OpenBLAS blas_thread_init: RLIMIT_NPROC 2950938 current, 2950938 max
OpenBLAS blas_thread_init: pthread_create: Resource temporarily unavailable
OpenBLAS blas_thread_init: RLIMIT_NPROC 2950938 current, 2950938 max
OpenBLAS blas_thread_init: pthread_create: Resource temporarily unavailable
OpenBLAS blas_thread_init: RLIMIT_NPROC 2950938 current, 2950938 max
Traceback (most recent call last):
File "/usr/lib/python3.5/multiprocessing/forkserver.py", line 178, in main
_serve_one(s, listener, alive_r, handler)
File "/usr/lib/python3.5/multiprocessing/forkserver.py", line 212, in _serve_one
code = spawn._main(child_r)
File "/usr/lib/python3.5/multiprocessing/spawn.py", line 115, in _main
prepare(preparation_data)
File "/usr/lib/python3.5/multiprocessing/spawn.py", line 226, in prepare
_fixup_main_from_path(data['init_main_from_path'])
File "/usr/lib/python3.5/multiprocessing/spawn.py", line 278, in _fixup_main_from_path
run_name="__mp_main__")
File "/usr/lib/python3.5/runpy.py", line 254, in run_path
pkg_name=pkg_name, script_name=fname)
File "/usr/lib/python3.5/runpy.py", line 96, in _run_module_code
mod_name, mod_spec, pkg_name, script_name)
File "/usr/lib/python3.5/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/anasys/chainermn/examples/imagenet/train_imagenet.py", line 9, in <module>
import numpy as np
File "/home/anasys/.local/lib/python3.5/site-packages/numpy/__init__.py", line 142, in <module>
from . import add_newdocs
File "/home/anasys/.local/lib/python3.5/site-packages/numpy/add_newdocs.py", line 13, in <module>
from numpy.lib import add_newdoc
File "/home/anasys/.local/lib/python3.5/site-packages/numpy/lib/__init__.py", line 8, in <module>
from .type_check import *
File "/home/anasys/.local/lib/python3.5/site-packages/numpy/lib/type_check.py", line 11, in <module>
import numpy.core.numeric as _nx
File "/home/anasys/.local/lib/python3.5/site-packages/numpy/core/__init__.py", line 16, in <module>
from . import multiarray
SystemError: initialization of multiarray raised unreported exception
ulimit -u を増やしたところで解決はしなかった。yak shaving が過ぎるので深く追ってないが無限ループしている?
AWSの環境では、chainermn/examples/imagenet/train_imagenet.py の下記の箇所をコメントアウトして、forkserver
方式を止めた所動いた。
# We need to change the start method of multiprocessing module if we are
# using InfiniBand and MultiprocessIterator. This is because processes
# often crash when calling fork if they are using Infiniband.
# (c.f., https://www.open-mpi.org/faq/?category=tuning#fork-warning )
- multiprocessing.set_start_method('forkserver')
+ # multiprocessing.set_start_method('forkserver')
train_iter = chainer.iterators.MultiprocessIterator(
train, args.batchsize, n_processes=args.loaderjob)
val_iter = chainer.iterators.MultiprocessIterator(
val, args.val_batchsize, repeat=False, n_processes=args.loaderjob)
python 3.5.2 の multiprocessing module の問題かもしれないが深く追ってない。