dlshogiをAWS inf1 インスタンスで動かせないか試している。
AWS inf1 インスタンスは、推論に特化したAWS Inferentia チップが搭載されている。
現在のdlshogiは、TensorRTを使用して推論を行っているため、NvidiaのGPUで動かすことが前提になっている。
onnxruntime版も用意しているが、推論速度は7.2倍ほど差がある。
dlshogiをAWSで動かそうとすると、NvidiaのGPUが搭載されたインスタンスを借りる必要がある。
しかし、NvidiaのGPUが搭載されたAWSのインスタンスの料金は高い。
AWS inf1 インスタンスは、NvidiaのGPUのインスタンスに比べるとリーズナブルである。
料金
推論向けのT4が搭載されたg4dnインスタンスと比較すると、バージニア北部で、以下の通りである。
インスタンス | vCPU | GPU | メモリ(GB) | スポットインスタンス料金 |
---|---|---|---|---|
g4dn.2xlarge | 8 | 1 | 32 | $0.2256 /1 時間 |
g4dn.12xlarge | 48 | 4 | 192 | $1.1761 /1 時間 |
inf1.2xlarge | 8 | 1 | 16 | $0.1086 /1 時間 |
inf1.6xlarge | 24 | 4 | 48 | $0.354 /1 時間 |
推論性能
推論性能は、カタログスペックで、以下の通りである。
T4 | 65 TFLOP(FP16) |
Inferentia | 128 TOPS |
ただし、dlshogiで実際に性能がでるかは測ってみないとわからない。
ということで、まずはPythonで、dlshogiのモデルの推論ができるか試してみた。
概要
Inferentiaを使用するには、neuron SDKを使用する必要がある。
neuron SDKは、TensorFlowやPyTorchをカスタマイズしたパッケージとして提供される。
Deep Learming AMIを使用すると、フレームワーク別のconda環境が用意されている。
ドキュメント参照:
Compile with Framework API and Deploy on EC2 Inf1 — AWS Neuron documentation
PyTorchで学習したモデルは、直接は利用できないため、Inferentia向けに変換を行う必要がある。
残念ながらモデルの形式は、onnxには対応していない。
onnxに変換前のモデルが必要である(dlshogi with GCTのモデルはonnxでしか公開していないので各自学習したモデルを使用する必要がある)。
なお、onnxからPyTorchに変換するツールを試したが、変換後の推論結果が一致せずうまくいかなかった。
手順
変換
モデルの変換は、inf1インスタンスでなくても実行できる。
c4.xlargeで、Deep Learming AMI(Ubuntu18)を使用して行った。
- ログイン後、
source activate aws_neuron_pytorch_p36
を実行し、PyTorchのneuron SDKの環境に切り替える。
- dlshogiのモデルをアップロードする。
- dlshogiのソースをgit cloneして、pip install -e .でパッケージをインストールする。
- 以下のスクリプトでモデルを変換する(ネットワークタイプとファイル名は書き換える)。
import torch import torch_neuron import torch.nn as nn from dlshogi.common import * from dlshogi.network.policy_value_network import policy_value_network from dlshogi import serializers from dlshogi import cppshogi model = policy_value_network('resnet15_swish', add_sigmoid=False) serializers.load_npz('model-pre5_resnet15_swish_b4096lr004-008', model, False) class PolicyValueNetworkAddSigmoid(nn.Module): def __init__(self, model): super(PolicyValueNetworkAddSigmoid, self).__init__() self.model = model def forward(self, x1, x2): y1, y2 = self.model(x1, x2) return y1, torch.sigmoid(y2) model = PolicyValueNetworkAddSigmoid(model) model.eval() def mini_batch(hcpevec): features1 = np.empty((len(hcpevec), FEATURES1_NUM, 9, 9), dtype=np.float32) features2 = np.empty((len(hcpevec), FEATURES2_NUM, 9, 9), dtype=np.float32) move = np.empty((len(hcpevec)), dtype=np.int64) result = np.empty((len(hcpevec)), dtype=np.float32) value = np.empty((len(hcpevec)), dtype=np.float32) cppshogi.hcpe_decode_with_value(hcpevec, features1, features2, move, result, value) z = result.astype(np.float32) - value + 0.5 return (torch.tensor(features1), torch.tensor(features2), torch.tensor(move.astype(np.int64)), torch.tensor(result.reshape((len(hcpevec), 1))), torch.tensor(z), torch.tensor(value.reshape((len(value), 1))) ) batchsize = 1 hcpevec = np.array([([ 88, 164, 73, 33, 12, 215, 87, 33, 126, 142, 77, 33, 44, 175, 66, 120, 20, 194, 171, 16, 158, 77, 33, 44, 215, 95, 33, 62, 142, 73, 33, 12], 0, 7739, 1, 0)] * batchsize, HuffmanCodedPosAndEval) x1, x2, t1, t2, z, value = mini_batch(hcpevec) model_neuron = torch.neuron.trace(model, example_inputs=[x1, x2], dynamic_batch_size=True) model_neuron.save('model-pre5_resnet15_swish_b4096lr004-008.neuron.pt')
推論
inf1.xlargeをスポットインスタンスで借りて試した。
※スポットインスタンスのvCPUの上限がデフォルト0になっていたので、制限解除の申請が必要だったがすぐに許可された。
- ログイン後、
source activate aws_neuron_pytorch_p36
を実行し、PyTorchのneuron SDKの環境に切り替える。
- 変換したモデルをアップロードする。
- 以下のスクリプトで推論を実行する。
import torch import torch_neuron import torch.nn as nn from dlshogi.common import * from dlshogi import cppshogi model = torch.jit.load('model-pre5_resnet15_swish_b4096lr004-008.neuron.pt') model.eval() def mini_batch(hcpevec): features1 = np.empty((len(hcpevec), FEATURES1_NUM, 9, 9), dtype=np.float32) features2 = np.empty((len(hcpevec), FEATURES2_NUM, 9, 9), dtype=np.float32) move = np.empty((len(hcpevec)), dtype=np.int64) result = np.empty((len(hcpevec)), dtype=np.float32) value = np.empty((len(hcpevec)), dtype=np.float32) cppshogi.hcpe_decode_with_value(hcpevec, features1, features2, move, result, value) z = result.astype(np.float32) - value + 0.5 return (torch.tensor(features1), torch.tensor(features2), torch.tensor(move.astype(np.int64)), torch.tensor(result.reshape((len(hcpevec), 1))), torch.tensor(z), torch.tensor(value.reshape((len(value), 1))) ) batchsize = 128 hcpevec = np.array([([ 88, 164, 73, 33, 12, 215, 87, 33, 126, 142, 77, 33, 44, 175, 66, 120, 20, 194, 171, 16, 158, 77, 33, 44, 215, 95, 33, 62, 142, 73, 33, 12], 0, 7739, 1, 0)] * batchsize, HuffmanCodedPosAndEval) x1, x2, t1, t2, z, value = mini_batch(hcpevec) print('start') for i in range(10000): y1, y2 = model(x1, x2)
- 別のコンソールから、/opt/aws/neuron/bin/neuron-topを実行することで、Inferentiaが使用されていることを確認できる。
neuron-top - 12:53:58 Models: 1 loaded, 1 running. NeuronCores: 1 used. 0000:00:1f.0 Utilizations: NC0 66.96%, NC1 0.00%, NC2 0.00%, NC3 0.00%, Model ID Device NeuronCore% Device Mem Host Mem Model Name 10016 nd0:nc0 66.96 29 MB 151 KB 1.5.5.0+3cc38c60b-/tmp/tmpmwpges2q