コンパイルとInferentia上での実行

事前学習済みの BERT モデルを Inferentia推論チップ向けにコンパイルし、Neuronコア上での推論処理を実行します。 コンパイル後のモデルの出力形式は TorchScript となります。

Step 1. コンパイル用 Python スクリプトを作成

章5.1で作成したinfer_bert_cpu.pyの最後に以下の内容を追加し、 compile_bert.py というファイル名のコンパイル用 Python スクリプトを作成します。

import torch.neuron

# Run torch.jit.trace to generate a TorchScript for running on CPU
model_cpu = torch.jit.trace(model, example_inputs_paraphrase)

# Run torch.neuron.trace to generate a TorchScript that is optimized by AWS Neuron
model_neuron = torch.neuron.trace(model, example_inputs_paraphrase)

# Save the TorchScripts for later use
model_cpu.save('bert_cpu.pt')
model_neuron.save('bert_neuron.pt')

Step 2. コンパイル用スクリプトを実行

コンパイル用スクリプト を実行します。inf1.2xlarge では~3分程度かかります。

time python compile_bert.py  
..
Compiler status PASS
INFO:Neuron:Number of arithmetic operators (post-compilation) before = 565, compiled = 548, percent compiled = 96.99%
INFO:Neuron:The neuron partitioner created 1 sub-graphs
INFO:Neuron:Neuron successfully compiled 1 sub-graphs, Total fused subgraphs = 1, Percent of model sub-graphs successfully compiled = 100.0%
INFO:Neuron:Compiled these operators (and operator counts) to Neuron:
INFO:Neuron: => aten::Int: 96
INFO:Neuron: => aten::add: 36
INFO:Neuron: => aten::contiguous: 12
INFO:Neuron: => aten::div: 12
INFO:Neuron: => aten::dropout: 38
INFO:Neuron: => aten::gelu: 12
INFO:Neuron: => aten::layer_norm: 25
INFO:Neuron: => aten::linear: 74
INFO:Neuron: => aten::matmul: 24
INFO:Neuron: => aten::permute: 48
INFO:Neuron: => aten::select: 1
INFO:Neuron: => aten::size: 96
INFO:Neuron: => aten::slice: 1
INFO:Neuron: => aten::softmax: 12
INFO:Neuron: => aten::tanh: 1
INFO:Neuron: => aten::transpose: 12
INFO:Neuron: => aten::view: 48
INFO:Neuron:Not compiled operators (and operator counts) to Neuron:
INFO:Neuron: => aten::Int: 1 [supported]
INFO:Neuron: => aten::add: 3 [supported]
INFO:Neuron: => aten::embedding: 3 [not supported]
INFO:Neuron: => aten::mul: 1 [supported]
INFO:Neuron: => aten::rsub: 1 [supported]
INFO:Neuron: => aten::size: 1 [supported]
INFO:Neuron: => aten::slice: 4 [supported]
INFO:Neuron: => aten::to: 1 [supported]
INFO:Neuron: => aten::unsqueeze: 2 [supported]

real    2m8.977s
user    2m5.834s
sys     0m9.073s

Neuron コンパイラでは、事前 (Ahead-Of-Time) コンパイルを行います。実行時 (JIT) コンパイラ や初回推論コンパイルシステムと比較すると、複数のインスタンス上にデプロイする場合において時間を節約できます。Neuron コンパイラは、自動的にオペレータを融合し、 スケジューリングとメモリ管理を行います。

Step 3. 推論実行 Python スクリプトを作成

以下の内容でinfer_bert_neuron.py というファイル名の推論実行 Python スクリプトを作成します。CPU上で推論を実行する場合と異なり、Step 2でコンパイルしたモデルを利用します。

import torch
import torch.neuron
from transformers import AutoTokenizer

# Build tokenizer
tokenizer = AutoTokenizer.from_pretrained("bert-base-cased-finetuned-mrpc")

# Load TorchScript back
model_neuron = torch.jit.load('bert_neuron.pt')

# Setup some example inputs
sequence_0 = "The company HuggingFace is based in New York City"
sequence_1 = "Apples are especially bad for your health"
sequence_2 = "HuggingFace's headquarters are situated in Manhattan"

paraphrase = tokenizer.encode_plus(sequence_0, sequence_2, max_length=128, padding='max_length', truncation=True, return_tensors="pt")
not_paraphrase = tokenizer.encode_plus(sequence_0, sequence_1, max_length=128, padding='max_length', truncation=True, return_tensors="pt")

# Convert example inputs to a format that is compatible with TorchScript tracing
example_inputs_paraphrase = paraphrase['input_ids'], paraphrase['attention_mask'], paraphrase['token_type_ids']
example_inputs_not_paraphrase = not_paraphrase['input_ids'], not_paraphrase['attention_mask'], not_paraphrase['token_type_ids']

# Verify the TorchScript works on both example inputs
paraphrase_classification_logits = model_neuron(*example_inputs_paraphrase)
not_paraphrase_classification_logits = model_neuron(*example_inputs_not_paraphrase)

classes = ['not paraphrase', 'paraphrase']
paraphrase_prediction = paraphrase_classification_logits[0][0].argmax().item()
not_paraphrase_prediction = not_paraphrase_classification_logits[0][0].argmax().item()
print('BERT says that "{}" and "{}" are {}'.format(sequence_0, sequence_2, classes[paraphrase_prediction]))
print('BERT says that "{}" and "{}" are {}'.format(sequence_0, sequence_1, classes[not_paraphrase_prediction]))

Step 4. 推論スクリプトを実行

Neuronコア上でのモデル推論を実行するために、推論実行スクリプトinfer_bert_neuron.py を実行します。

python infer_bert_neuron.py

CPU上で実行した場合と同様の次の結果が取得されます。

BERT says that "The company HuggingFace is based in New York City" and "HuggingFace's headquarters are situated in Manhattan" are paraphrase
BERT says that "The company HuggingFace is based in New York City" and "Apples are especially bad for your health" are not paraphrase