ONNXRuntime Transformer模型优化工具
项目描述
Transformer模型优化工具概述
ONNX Runtime在加载transformer模型时自动应用大多数优化。一些尚未集成到ONNX Runtime的最新优化可以在该工具中找到,以获得最佳性能。
该工具可以帮助以下场景:
- 模型由tf2onnx或keras2onnx导出,而ONNX Runtime目前没有针对它们的图优化。
- 将模型转换为使用float16以在具有Tensor Cores的GPU(如V100或T4)上使用混合精度来提升性能。
- 模型有具有动态轴的输入,这由于形状推断而阻止了ONNX Runtime应用某些优化。
- 禁用或启用某些融合以查看其对性能或准确性的影响。
安装
首先您需要安装用于CPU或GPU推理的onnxruntime或onnxruntime-gpu包。要使用onnxruntime-gpu,需要安装CUDA和cuDNN,并将它们的bin目录添加到PATH环境变量中。
限制
由于Attention内核的CUDA实现,最大注意力头数为1024。通常,Longformer的最大支持序列长度为4096,其他类型模型为1024。
将Transformer模型导出到ONNX
PyTorch 可以将模型导出为 ONNX 格式。tf2onnx 和 keras2onnx 工具可以用于将 TensorFlow 训练的模型转换为 ONNX 格式。Huggingface Transformers 有一个 笔记本 展示了将预训练模型导出到 ONNX 的示例。对于 Keras2onnx,请参阅其 示例脚本。对于 tf2onnx,请参阅其 BERT 教程。
GPT-2 模型转换
当使用过去状态时,将 PyTorch 的 GPT-2 模型转换为 ONNX 并不简单。我们添加了一个 convert_to_onnx 工具来帮助您。
您可以使用以下命令将预训练的 PyTorch GPT-2 模型转换为 ONNX,适用于给定的精度(float32、float16 或 int8)
python -m onnxruntime.transformers.convert_to_onnx -m gpt2 --model_class GPT2LMHeadModel --output gpt2.onnx -p fp32
python -m onnxruntime.transformers.convert_to_onnx -m distilgpt2 --model_class GPT2LMHeadModel --output distilgpt2.onnx -p fp16 --use_gpu --optimize_onnx
python -m onnxruntime.transformers.convert_to_onnx -m [path_to_gpt2_pytorch_model_directory] --output quantized.onnx -p int32 --optimize_onnx
此工具还将验证当使用相同的随机输入时,ONNX 模型和相应的 PyTorch 模型是否生成相同的输出。
Longformer 模型转换
要求:Linux 操作系统(例如 Ubuntu 18.04 或 20.04)以及以下类似的 Python 环境
conda create -n longformer python=3.6
conda activate longformer
conda install pytorch torchvision torchaudio cpuonly -c pytorch
pip install onnx transformers onnxruntime
接下来,获取 Longformer 导出所需的 torch 扩展 的源代码,并运行以下命令
python setup.py install
它将在目录下生成类似 "build/lib.linux-x86_64-3.6/longformer_attention.cpython-36m-x86_64-linux-gnu.so" 的文件。
最后,使用 convert_longformer_to_onnx 将模型转换为以下 ONNX 模型
python convert_longformer_to_onnx.py -m longformer-base-4096
目前导出的 ONNX 模型只能在 GPU 上运行。
模型优化器
在您的 Python 代码中,您可以使用以下优化器
from onnxruntime.transformers import optimizer
optimized_model = optimizer.optimize_model("gpt2.onnx", model_type='gpt2', num_heads=12, hidden_size=768)
optimized_model.convert_model_float32_to_float16()
optimized_model.save_model_to_file("gpt2_fp16.onnx")
您也可以使用命令行。以下是将 BERT-large 模型优化为使用混合精度(float16)的示例
python -m onnxruntime.transformers.optimizer --input bert_large.onnx --output bert_large_fp16.onnx --num_heads 16 --hidden_size 1024 --float16
您也可以从 此处 下载最新的脚本文件。然后按照以下方式运行
python optimizer.py --input gpt2.onnx --output gpt2_opt.onnx --model_type gpt2
优化器选项
以下是对 optimizer.py 中一些选项的描述
- input:输入模型路径
- output:输出模型路径
- model_type:(默认:bert) 有 4 种模型类型:bert(由 PyTorch 导出)、gpt2(由 PyTorch 导出)、bert_tf(由 tf2onnx 导出的 BERT)和 bert_keras(由 keras2onnx 导出的 BERT)。
- num_heads:(默认:12) 注意力头数。BERT-base 和 BERT-large 分别有 12 和 16 个。
- hidden_size:(默认:768) BERT-base 和 BERT-large 分别有 768 和 1024 个隐藏节点。
- input_int32:(可选) 通常导出的模型使用 int64 张量作为输入。如果指定此标志,则使用 int32 张量作为输入,并且可以避免不必要的 Cast 节点并获得更好的性能。
- float16:(可选) 默认情况下,模型使用 float32 进行计算。如果指定此标志,则使用半精度浮点数。此选项建议用于具有 Tensor Core 的 NVidia GPU,例如 V100 和 T4。对于较旧的 GPU,float32 可能更快。
- use_gpu:(可选) 当 opt_level > 1 时,请为此标志设置 GPU 推理。
- opt_level:(可选) 设置 OnnxRuntime 的适当图优化级别:0 - 禁用所有(默认),1 - 基本优化,2 - 扩展优化,99 - 所有优化。如果值为正,OnnxRuntime 首先用于优化图。
- verbose:(可选) 当指定此标志时,打印详细信息。
支持的模式
以下是在使用优化器测试过的来自 Huggingface Transformers 的 PyTorch 模型列表
- BERT
- DistilBERT
- DistilGPT2
- RoBERTa
- ALBERT
- GPT-2 (模型, LMHead模型)
对于Tensorflow模型,目前我们只测试了BERT模型。
大多数优化都需要子图的精确匹配。子图中的任何布局更改都可能导致某些优化不起作用。请注意,不同版本的训练或导出工具可能会导致不同的图布局。建议使用PyTorch和Transformers的最新发布版本。
如果你的模型不在列表中,它可能只部分优化或根本没有优化。
基准测试
有一个用于运行基准测试的bash脚本run_benchmark.sh。在运行之前,你可以修改bash脚本来选择你的选项(如要测试的模型、批大小、序列长度、目标设备等)。
该bash脚本将调用benchmark.py脚本来测量OnnxRuntime、PyTorch或PyTorch+TorchScript在Huggingface Transformers预训练模型上的推理性能。
V100上的基准测试结果
在以下基准测试结果中,ONNX Runtime使用优化器进行模型优化,并且启用了IO绑定。
我们在Tesla V100-PCIE-16GB GPU(CPU是Intel Xeon(R) E5-2690 v4)上测试了不同的批大小(b)和序列长度(s)。以下结果为每次推理的平均延迟(毫秒)。
bert-base-uncased (BertModel)
该模型有12层和768个隐藏层,以input_ids作为输入。
引擎 | 版本 | 精度 | b | s=8 | s=16 | s=32 | s=64 | s=128 | s=256 | s=512 |
---|---|---|---|---|---|---|---|---|---|---|
torchscript | 1.5.1 | fp32 | 1 | 7.92 | 8.78 | 8.91 | 9.18 | 9.56 | 9.39 | 12.83 |
onnxruntime | 1.4.0 | fp32 | 1 | 1.38 | 1.42 | 1.67 | 2.15 | 3.11 | 5.37 | 10.74 |
onnxruntime | 1.4.0 | fp16 | 1 | 1.30 | 1.29 | 1.31 | 1.33 | 1.45 | 1.95 | 3.36 |
onnxruntime | 1.4.0 | fp32 | 4 | 1.51 | 1.93 | 2.98 | 5.01 | 9.13 | 17.95 | 38.15 |
onnxruntime | 1.4.0 | fp16 | 4 | 1.27 | 1.35 | 1.43 | 1.83 | 2.66 | 4.40 | 9.76 |
run_benchmark.sh用于获取结果。
gpt2 (GPT2LMHeadModel)
该模型有12层和768个隐藏层,以input_ids、position_ids、attention_mask和过去状态作为输入。
引擎 | 版本 | 精度 | b | s=4 | s=8 | s=32 | s=128 |
---|---|---|---|---|---|---|---|
torchscript | 1.5.1 | fp32 | 1 | 5.80 | 5.77 | 5.82 | 5.78 |
onnxruntime | 1.4.0 | fp32 | 1 | 1.42 | 1.42 | 1.43 | 1.47 |
onnxruntime | 1.4.0 | fp16 | 1 | 1.54 | 1.54 | 1.58 | 1.64 |
onnxruntime | 1.4.0 | fp32 | 8 | 1.83 | 1.84 | 1.90 | 2.13 |
onnxruntime | 1.4.0 | fp16 | 8 | 1.74 | 1.75 | 1.81 | 2.09 |
onnxruntime | 1.4.0 | fp32 | 32 | 2.19 | 2.21 | 2.45 | 3.34 |
onnxruntime | 1.4.0 | fp16 | 32 | 1.66 | 1.71 | 1.85 | 2.73 |
onnxruntime | 1.4.0 | fp32 | 128 | 4.15 | 4.37 | 5.15 | 8.61 |
onnxruntime | 1.4.0 | fp16 | 128 | 2.47 | 2.58 | 3.26 | 6.16 |
由于使用了过去状态,input_ids中的序列长度为1。例如,s=4表示过去序列长度为4,总序列长度为5。
benchmark_gpt2.py用于获取以下命令类似的结果
python -m onnxruntime.transformers.benchmark_gpt2 --use_gpu -m gpt2 -o -v -b 1 8 32 128 -s 4 8 32 128 -p fp32
python -m onnxruntime.transformers.benchmark_gpt2 --use_gpu -m gpt2 -o -v -b 1 8 32 128 -s 4 8 32 128 -p fp16
Benchmark.py
如果你使用run_benchmark.sh,你不需要直接使用benchmark.py。如果你不想了解详细信息,可以跳过此部分。
以下是在GPU上运行预训练模型bert-base-cased的benchmark.py的示例。
python -m onnxruntime.transformers.benchmark -g -m bert-base-cased -o -v -b 0
python -m onnxruntime.transformers.benchmark -g -m bert-base-cased -o
python -m onnxruntime.transformers.benchmark -g -m bert-base-cased -e torch
python -m onnxruntime.transformers.benchmark -g -m bert-base-cased -e torchscript
第一条命令将生成ONNX模型(优化前后),但由于批大小为0,不会运行性能测试。其他三个命令将对每个三个引擎(OnnxRuntime、PyTorch和PyTorch+TorchScript)运行性能测试。
如果你删除了-o参数,则不在基准测试中使用优化器脚本。
如果你的GPU(如V100或T4)具有TensorCore,你可以在上述命令后追加-p fp16
以启用混合精度。
如果你想在CPU上基准测试,你可以在命令中删除-g选项。
请注意,我们目前对GPT2和DistilGPT2模型的基准测试已禁用输入和输出中的过去状态。
默认情况下,ONNX模型只有一个输入(input_ids)。你可以使用-i参数来测试具有多个输入的模型。例如,我们可以将"-i 3"添加到命令行来测试一个有3个输入(input_ids、token_type_ids和attention_mask)的bert模型。此选项目前仅支持OnnxRuntime。
BERT模型验证
如果你的BERT模型有三个输入(如input_ids、token_type_ids和attention_mask),可以使用compare_bert_results.py脚本来进行快速验证。该工具将生成一些伪造的输入数据,并比较原始和优化模型的输出结果。如果输出结果都很接近,则可以使用优化后的模型。
针对CPU优化的模型验证示例
python -m onnxruntime.transformers.compare_bert_results --baseline_model original_model.onnx --optimized_model optimized_model_cpu.onnx --batch_size 1 --sequence_length 128 --samples 100
对于GPU,请在命令中追加--use_gpu。
性能测试
可以使用bert_perf_test.py来检查BERT模型推理性能。以下是示例:
python -m onnxruntime.transformers.bert_perf_test --model optimized_model_cpu.onnx --batch_size 1 --sequence_length 128
对于GPU,请在命令中追加--use_gpu。
测试完成后,将在模型目录中输出类似于perf_results_CPU_B1_S128_<date_time>.txt或perf_results_GPU_B1_S128_<date_time>.txt的文件。
性能分析
可以使用profiler.py在Transformer模型上运行性能分析。它可以帮助找出模型的瓶颈以及节点或子图上花费的CPU时间。
示例命令
python -m onnxruntime.transformers.profiler --model bert.onnx --batch_size 8 --sequence_length 128 --samples 1000 --dummy_inputs bert --thread_num 8 --kernel_time_only
python -m onnxruntime.transformers.profiler --model gpt2.onnx --batch_size 1 --sequence_length 1 --past_sequence_length 128 --samples 1000 --dummy_inputs gpt2 --use_gpu
python -m onnxruntime.transformers.profiler --model longformer.onnx --batch_size 1 --sequence_length 4096 --global_length 8 --samples 1000 --dummy_inputs longformer --use_gpu
结果文件,如onnxruntime_profile__<date_time>.json,将被输出到当前目录。节点摘要、最昂贵的节点和按操作类型分组的结果的总结将被打印到控制台。
项目详情
下载文件
下载适合您平台文件的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。
源代码发行版
构建发行版
onnxruntime_tools-1.7.0.tar.gz的哈希
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 6dbdcee49424e066bcd10357c37d51bc422ae26494e3c2f0c1970d534f967f6d |
|
MD5 | 56a4cf5a6f4377f9c0d5cab8a89de83c |
|
BLAKE2b-256 | fdb5c36283fef3b1d492a39d1b5f3f195965fbf002b168633daad302c51d8f4c |
onnxruntime_tools-1.7.0-py3-none-any.whl的哈希
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 1dff888b5c482ac5bc627f12e108445fefcb3d600c43f63633975316fe617ad8 |
|
MD5 | ac49e13b3d4f838d837b529c9866f76c |
|
BLAKE2b-256 | 6fb0db0e73356df0aaa8737e6f13c0dac499b5d904d3fa267c8ebf24515e8001 |