章4.3で得られた結果を検証し、Neuronコア上での推論処理の最適化を試みます。
Neuronコア上での推論処理が実行されている間に、別のターミナル上で neuron-top
ツールを使用して Neuronコアの利用率を確認します。
neuron-top
出力結果から Inferentia推論チップ上の4つの Neuron コアそれぞれが、15~20%程度の負荷で利用されていることが確認できます。
NeuronCore Utilization
NC0 NC1 NC2 NC3
ND0 |||||||||||||||[19.34%] ||||||||||||||||||||[19.62%] ||||||||||||||||||||[19.64%] ||||||||||||||||||||[19.64%]
vCPU and Memory Info
System vCPU Usage ||||||||||||||||||||||||[10.97%,17.40%] Runtime vCPU Usage |||||||||||||||||||||||[ 2.77%, 1.13%]
Runtime Memory Host ||||||||||||||||||[ 9.9MB/ 15.2GB] Runtime Memory Device 207.5MB
Loaded Models
Model ID
[+] ND 0
章4.3のスクリプト infer_resnet50_perf.py
のままではNeuronコア上での推論処理が数秒で終了してしまうため、繰り返し回数 num_inferences
を大きくし、またCPU上での推論処理をコメントアウトして再度実行して下さい。
以下の内容でinfer_resnet50_perf2.py
というファイル名の推論実行 Python スクリプトを作成します。
本スクリプトでは、Inferentia推論チップ上に搭載される 4つの Neuron コアを効率的に活用すべく、Python の ThreadPoolExecutor を用いて並列にスレッドを実行し、Neuronコアの負荷を最大まで高めるテストを行います。
import os
import time
import numpy as np
import tensorflow as tf
from tensorflow.keras.preprocessing import image
from tensorflow.keras.applications.resnet50 import ResNet50, preprocess_input, decode_predictions
from concurrent import futures
# added for utilizing 4 neuron cores
os.environ['NEURON_RT_VISIBLE_CORES'] = '0-3'
# Load models
model_dir = 'resnet50'
predictor_cpu = tf.contrib.predictor.from_saved_model(model_dir)
compiled_model_dir = 'resnet50_neuron'
predictor_inferentia = tf.contrib.predictor.from_saved_model(compiled_model_dir)
# Create input from image
img_sgl = image.load_img('kitten_small.jpg', target_size=(224, 224))
img_arr = image.img_to_array(img_sgl)
img_arr2 = np.expand_dims(img_arr, axis=0)
img_arr3 = preprocess_input(img_arr2)
model_feed_dict={'input': img_arr3}
# warmup
infa_rslts = predictor_cpu(model_feed_dict)
infa_rslts = predictor_inferentia(model_feed_dict)
num_inferences = 1000
# Run inference on CPUs, Display results
start = time.time()
with futures.ThreadPoolExecutor(8) as exe:
fut_list = []
for _ in range (num_inferences):
fut = exe.submit(predictor_cpu, model_feed_dict)
fut_list.append(fut)
for fut in fut_list:
infa_rslts = fut.result()
elapsed_time = time.time() - start
print('By CPU - num_inferences:{:>6}[images], elapsed_time:{:6.2f}[sec], Throughput:{:8.2f}[images/sec]'.format(num_inferences, elapsed_time, num_inferences / elapsed_time))
# Run inference on Neuron Cores, Display results
start = time.time()
with futures.ThreadPoolExecutor(8) as exe:
fut_list = []
for _ in range (num_inferences):
fut = exe.submit(predictor_inferentia, model_feed_dict)
fut_list.append(fut)
for fut in fut_list:
infa_rslts = fut.result()
elapsed_time = time.time() - start
print('By Neuron Core - num_inferences:{:>6}[images], elapsed_time:{:6.2f}[sec], Throughput:{:8.2f}[images/sec]'.format(num_inferences, elapsed_time, num_inferences / elapsed_time))
変更後の推論実行スクリプトinfer_resnet50_perf2.py
を実行します。
python infer_resnet50_perf2.py
次の結果が取得されます。Neuronコア上での処理性能が大幅に向上している事が確認できます。
By CPU - num_inferences: 1000[images], elapsed_time: 39.21[sec], Throughput: 25.50[images/sec]
By Neuron Core - num_inferences: 1000[images], elapsed_time: 1.27[sec], Throughput: 788.13[images/sec]
Step 1.と同様に Neuronコアの利用率を確認します。
neuron-top
出力結果から 4つの Neuron コアそれぞれが、~100%の高負荷で利用されていることが確認できます。
NeuronCore Utilization
NC0 NC1 NC2 NC3
ND0 |||||||||||||||[99.61%] ||||||||||||||||||||[ 100%] ||||||||||||||||||||[99.89%] ||||||||||||||||||||[99.76%]
vCPU and Memory Info
System vCPU Usage ||||||||||||||||||||||||[21.22%,10.12%] Runtime vCPU Usage |||||||||||||||||||||||[18.98%, 9.28%]
Runtime Memory Host ||||||||||||||||||[ 9.9MB/ 15.2GB] Runtime Memory Device 207.5MB
Loaded Models
Model ID
[+] ND 0