4. 模型编译
在 Section 2.3, IPU推理方案架构 中提到,IPU推理方案分为模型编译和模型运行时两个阶段。本章将以ONNX、TensorFlow和PyTorch的模型为例,阐述如何通过 PopRT 将不同框架导出的模型转换和编译成 PopEF 格式的二进制文件。
备注
本章中的示例需要Python环境,请确保已经安装
python
和virtualenv
。示例中的命令较长,在PDF格式下拷贝命令请注意被换行符或者分页截断的命令。
备注
本节中将使用 Section 3.6.1, 通过容器安装 中的容器镜像
4.1. ONNX模型
本节将以ONNX模型为例,讲述如何进行模型转换并编译生成PopEF。本节将以 ONNX model zoo 中的 BERT-Squad 模型为例。
创建本示例所需的目录和Python虚拟环境。
$ mkdir -p onnx_bert && \
cd onnx_bert && \
virtualenv -p python3 venv && \
source venv/bin/activate && \
pip install protobuf==3.19 onnx==1.11 && \
deactivate
4.1.1. 模型导出
通过 wget
命令下载ONNX model zoo中的 bertsquad-12.onnx
模型。
$ wget https://github.com/onnx/models/raw/87d452a218093f6a60ceb62712ffe1186dce6d64/text/machine_comprehension/bert-squad/model/bertsquad-12.onnx
4.1.2. 选择batch size
在编译阶段需要确定batch size的大小,在PopRT命令行中batch size的确定是通过 input_shape
参数指定的。在指定 input_shape
参数时,需要知道输入的tensor的名称,可以通过ONNX Python API获取。
$ source venv/bin/activate
$ cat > list_input.py << EOF
import onnx
model = onnx.load('bertsquad-12.onnx')
graph = model.graph
print(graph.input)
EOF
$ python list_input.py
$ deactivate
得到如下的输出:
[name: "unique_ids_raw_output___9:0"
type {
tensor_type {
elem_type: 7
shape {
dim {
dim_param: "unk__492"
}
}
}
}
, name: "segment_ids:0"
type {
tensor_type {
elem_type: 7
shape {
dim {
dim_param: "unk__493"
}
dim {
dim_value: 256
}
}
}
}
, name: "input_mask:0"
type {
tensor_type {
elem_type: 7
shape {
dim {
dim_param: "unk__494"
}
dim {
dim_value: 256
}
}
}
}
, name: "input_ids:0"
type {
tensor_type {
elem_type: 7
shape {
dim {
dim_param: "unk__495"
}
dim {
dim_value: 256
}
}
}
}
]
可以从中获得输入的参数名称和维度,在此我们使用batch size 16,对应的 input_shape
参数设置如下:
--input_shape input_ids:0=16,256 input_mask:0=16,256 segment_ids:0=16,256 unique_ids_raw_output___9:0=16
4.1.3. 选择精度
ONNX model zoo中的bertsquad-12.onnx模型采用的是FP32的精度,IPU推荐使用FP16的精度。在PopRT中精度是通过参数 --precision fp16
指定的,关于更多参数的信息请参考 PopRT User Guide 。
--precision fp16
4.1.4. 模型转换和编译
通过以下的命令将 bertsquad-12.onnx
模型转换为使用FP16精度,batch size为16,可以通过PopART运行的ONNX模型,并保存至
bertsquad-12_fp16_bs_16.onnx
。同时会将转换出来的模型编译为PopEF格式的二进制文件 executable.popef
。
如果不指定 --export_popef
参数,则单独执行模型转换的任务。更多模型转换的参数请参考 PopRT 文档。
$ gc-docker -- --rm \
-v `pwd -P`:/model_conversion \
-w /model_conversion \
graphcorecn/poprt-staging:latest \
--input_model bertsquad-12.onnx \
--output_model bertsquad-12_fp16_bs_16.onnx \
--input_shape input_ids:0=16,256 input_mask:0=16,256 segment_ids:0=16,256 unique_ids_raw_output___9:0=16 \
--precision fp16 \
--convert_version 11 \
--export_popef \
--ipu_version ipu21
备注
如果在IPU-M2000或Bow-2000的环境中测试, 请使用 --ipu_version ipu2
模型转换成功,在目录中包含以下文件:
$ tree . -L 1
.
├── bertsquad-12.onnx
├── bertsquad-12_fp16_bs_16.onnx
├── executable.popef
├── list_input.py
└── venv
where:
bertsquad-12.onnx
是原模型bertsquad-12_fp16_bs_16.onnx
是通过PopRT转换后的模型executable.popef
是编译得到的PopEF文件
备注
本示例完成,请通过 cd ..
回到测试根目录
4.2. TensorFlow模型
本节将以 TensorFlow Hub 中的 ResNet_v2_50 模型为例,讲述如何将TensorFlow模型转换并编译生成PopEF。
创建本示例所需的目录和Python虚拟环境。
$ mkdir -p tensorflow_resnet
$ cd tensorflow_resnet
$ virtualenv -p python3 venv
$ source venv/bin/activate
$ pip install protobuf==3.19 tensorflow==2.6 onnx==1.11 tf2onnx==1.12.1 packaging
$ deactivate
4.2.1. 模型导出
从TensorFlow Hub下载 ResNet_v2_50
模型并解压到指定目录:
$ wget -O resnet_v2_50.tar.gz https://tfhub.dev/google/imagenet/resnet_v2_50/classification/5?tf-hub-format=compressed
$ mkdir resnet_v2_50
$ tar -xf resnet_v2_50.tar.gz -C resnet_v2_50
在 Section 2.3, IPU推理方案架构 中提到,IPU推理方案使用ONNX模型作为统一的输入模型,需要通过 tf2onnx 工具将其转成ONNX模型。
执行以下命令将SavedModel模型转换为ONNX模型:
$ source venv/bin/activate
$ python -m tf2onnx.convert \
--saved-model resnet_v2_50 \
--output resnet_v2_50.onnx \
--inputs-as-nchw inputs \
--outputs-as-nchw logits \
--opset 11
$ deactivate
由于PopART支持的tensor格式是nchw,需要使用 --inputs-as-nchw inputs
和 --outputs-as-nchw logits
将输入和输出tensor从nhwc格式转换成nchw格式。参数 inputs
和 logits
分别为输入和输出的tensor名称,它们可以通过TensorFlow标准工具 saved_model_cli
从模型中读取:
$ source venv/bin/activate
$ python -m tensorflow.python.tools.saved_model_cli \
show \
--dir resnet_v2_50/ \
--all
$ deactivate
输出节选如下:
signature_def['serving_default']:
The given SavedModel SignatureDef contains the following input(s):
inputs['inputs'] tensor_info:
dtype: DT_FLOAT
shape: (-1, -1, -1, 3)
name: serving_default_inputs:0
The given SavedModel SignatureDef contains the following output(s):
outputs['logits'] tensor_info:
dtype: DT_FLOAT
shape: (-1, 1001)
name: StatefulPartitionedCall:0
Method name is: tensorflow/serving/predict
其中, inputs['inputs'] tensor_info
描述了该输入名称为 inputs
。 同理, outputs['logits'] tensor_info
描述了该输出名称为 logits
。
4.2.2. 模型转换和编译
这里仅描述使用PopRT进行float16模型编译,如需进行其他优化策略如修改 batch_size
等,请参考 Section 4.1, ONNX模型 。
由于IPU使用静态编译,需要确定 input_shape
。对于该模型,我们使用 inputs=(4,3,224,224)
进行编译。输入模型为 Section 4.2.1, 模型导出 中获得的 resnet_v2_50.onnx
模型。
$ gc-docker -- --rm \
-v `pwd -P`:/model_conversion \
-w /model_conversion \
graphcorecn/poprt-staging:latest \
--input_model resnet_v2_50.onnx \
--precision fp16 \
--output_model resnet_v2_50_optimized.onnx \
--input_shape inputs=4,3,224,224 \
--convert_version 11 \
--export_popef \
--ipu_version ipu21
备注
如果在IPU-M2000或Bow-2000环境中测试,请使用 --ipu_version ipu2
。
模型转换成功,目录中产生转换后的ONNX文件 resnet_v2_50_optimized.onnx
,以及编译得到的PopEF文件 file executable.popef
。
$ tree . -L 1
.
├── executable.popef
├── resnet_v2_50
├── resnet_v2_50.onnx
├── resnet_v2_50.tar.gz
├── resnet_v2_50_optimized.onnx
└── venv
备注
本示例完成,请通过 cd ..
回到测试根目录
4.3. PyTorch模型
本节将以 torchvision 中的 resnet50 为例,讲述如何将PyTorch的模型转换并编译生成PopEF文件。
创建本示例所需的目录和Python虚拟环境。
$ mkdir -p torch_resnet
$ cd torch_resnet
$ virtualenv -p python3 venv
$ source venv/bin/activate
$ pip install torchvision==0.11.2
$ deactivate
4.3.1. 模型导出
首先通过 torchvision
加载 resnet50
模型,确定 batch size
的大小和输入的shape,并将其导出为ONNX文件。
$ source venv/bin/activate
$ cat > export.py << EOF
import torch.onnx
import torchvision.models as models
model = models.resnet50(pretrained=True)
BATCH_SIZE = 4
dummy_input = torch.randn(BATCH_SIZE, 3, 244, 244)
model.eval() # save it to onnx
torch.onnx.export(model, dummy_input, 'resnet50.onnx', opset_version=11)
print('The model saved into resnet50.onnx')
EOF
$ python export.py
$ deactivate
4.3.2. 模型转换和编译
得到的ONNX模型(resnet50.onnx
),通过以下的命令进行转换和编译,关于命令中的参数解释,请参考 Section 4.1, ONNX模型 中的内容。
$ gc-docker -- --rm \
-v `pwd -P`:/model_conversion \
-w /model_conversion \
graphcorecn/poprt-staging:latest \
--input_model resnet50.onnx \
--precision fp16 \
--export_popef \
--ipu_version ipu21
备注
如果在IPU-M2000或Bow-2000环境中测试,请使用 --ipu_version ipu2
命令成功执行,目录中将生成以下文件:
$ tree . -L 1
.
├── executable.popef
├── export.py
├── resnet50.onnx
├── resnet50.onnx.optimized.onnx
└── venv
其中:
resnet50.onnx
是原始模型optimized.onnx
是由PopRT转换得到的模型executable.popef
是编译得到的PopEF文件
备注
本示例完成,请通过 cd ..
回到测试根目录