Inferentia上で推論性能最適化

章4.3で得られた結果を検証し、Neuronコア上での推論処理の最適化を試みます。

Step 1. 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上での推論処理をコメントアウトして再度実行して下さい。

Step 2. 推論スクリプトの変更

以下の内容で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))

Step 3. 変更後の推論スクリプトを実行

変更後の推論実行スクリプト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 4. Neuronコアの負荷測定

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