ONNX 模型在 MLIR 编译器基础设施中的表示和参考下推
此项目由 onnx 维护
托管于 GitHub Pages — 主题来自 orderedlist
当 onnx-mlir 编译的推理可执行文件产生的数值结果与训练框架产生的结果不一致时,请使用 utils/RunONNXModel.py
Python 脚本进行调试。此 Python 脚本将通过 onnx-mlir 和一个参考后端运行模型,并逐层比较这两个后端产生的中间结果。
ONNX_MLIR_HOME
环境变量设置为 onnx-mlir 的 HOME 目录路径。onnx-mlir 的 HOME 目录是指包含 bin
、lib
等子文件夹的父文件夹,这些子文件夹中可以找到 ONNX-MLIR 的可执行文件和库。onnx-mlir 的输出可以通过使用参考 ONNX 后端或 protobuf 中的参考输入和输出来验证。
pip install onnxruntime
来安装 onnxruntime。要使用不同的测试后端,只需将导入 onnxruntime 的代码替换为其他符合 ONNX 标准的后端即可。--verify=ref --load-ref=data_folder
,其中 data_folder
是包含输入和输出的 protobuf 文件的文件夹路径。 此指南介绍了如何从 numpy 数组创建 protobuf 文件。utils/RunONNXModel.py
支持以下命令行选项
$ python ../utils/RunONNXModel.py --help
usage: RunONNXModel.py [-h] [--log-to-file [LOG_TO_FILE]] [--model MODEL] [--compile-args COMPILE_ARGS] [--compile-only] [--compile-using-input-shape] [--print-input]
[--print-output] [--save-onnx PATH] [--verify {onnxruntime,ref}] [--verify-all-ops] [--verify-with-softmax] [--verify-every-value] [--rtol RTOL]
[--atol ATOL] [--save-so PATH | --load-so PATH] [--save-ref PATH] [--load-ref PATH | --shape-info SHAPE_INFO] [--lower-bound LOWER_BOUND]
[--upper-bound UPPER_BOUND]
optional arguments:
-h, --help show this help message and exit
--log-to-file [LOG_TO_FILE] Output compilation messages to file, default compilation.log
--model MODEL Path to an ONNX model (.onnx or .mlir)
--compile-args COMPILE_ARGS Arguments passed directly to onnx-mlir command. See bin/onnx-mlir --help
--compile-only Only compile the input model
--compile-using-input-shape Compile the model by using the shape info getting from the inputs in the reference folder set by --load-ref
--print-input Print out inputs
--print-output Print out inference outputs produced by onnx-mlir
--save-onnx PATH File path to save the onnx model. Only effective if --verify=onnxruntime
--verify {onnxruntime,ref} Verify the output by using onnxruntime or reference inputs/outputs. By default, no verification. When being enabled, --verify-with-softmax or --verify-every-value must be used to specify verification mode.
--verify-all-ops Verify all operation outputs when using onnxruntime
--verify-with-softmax Verify the result obtained by applying softmax to the output
--verify-every-value Verify every value of the output using atol and rtol
--rtol RTOL Relative tolerance for verification
--atol ATOL Absolute tolerance for verification
--save-so PATH File path to save the generated shared library of the model
--load-so PATH File path to load a generated shared library for inference, and the ONNX model will not be re-compiled
--save-ref PATH Path to a folder to save the inputs and outputs in protobuf
--load-ref PATH Path to a folder containing reference inputs and outputs stored in protobuf. If --verify=ref, inputs and outputs are reference data for verification
--shape-info SHAPE_INFO Shape for each dynamic input of the model, e.g. 0:1x10x20,1:7x5x3. Used to generate random inputs for the model if --load-ref is not set
--lower-bound LOWER_BOUND Lower bound values for each data type. Used inputs. E.g. --lower-bound=int64:-10,float32:-0.2,uint8:1. Supported types are bool, uint8, int8, uint16, int16, uint32, int32, uint64, int64,float16, float32, float64
--upper-bound UPPER_BOUND Upper bound values for each data type. Used to generate random inputs. E.g. --upper-bound=int64:10,float32:0.2,uint8:9. Supported types are bool, uint8, int8, uint16, int16, uint32, int32, uint64, int64, float16, float32, float64
基于上述 utils/runONNXModel.py
,utils/checkONNXModel.py
允许用户在两个不同的编译选项下运行给定模型两次,并比较其结果。这使得用户可以简单地测试一个新选项,将编译器的安全版本(例如 -O0
或 -O3
)与更高级的版本(例如 -O3
或 -O3 --march=x86-64
)进行比较。只需使用 --ref-compile-args
和 --test-compile-args
标志指定编译选项,使用 --model
标志指定模型,并在存在动态形状输入时可能指定 --shape-info
。完整选项列在 --help
标志下。
如果您知道或怀疑某个 ONNX MLIR 算子产生了不正确的结果,并希望缩小问题范围,我们提供了几个有用的 Krnl 算子,它们允许在运行时打印张量的值或具有基本数据类型的值。
要在特定程序点打印张量的值,请注入以下代码(其中 X
是要打印的张量)
create.krnl.printTensor("Tensor X: ", X);
注意:目前,只有当张量秩小于四时,才会打印张量的内容。
要打印一条消息后跟一个值,请注入以下代码(其中 val
是要打印的值,valType
是其类型)
create.krnl.printf("inputElem: ", val, valType);
如果您知道或怀疑 onnx-mlir 编译的推理可执行文件存在内存分配相关问题,可以使用 valgrind 框架或 mtrace 内存工具来协助调试。这些工具可以跟踪内存分配/释放相关的 API,并能检测内存问题,例如内存泄漏。
然而,如果内存访问相关的问题,特别是缓冲区溢出问题,调试起来非常困难,因为运行时错误发生在问题的发生点之外。可以使用 “Electric Fence 库”来调试这些问题。它有助于检测两种常见的编程问题:超出 malloc() 内存分配边界的软件,以及访问已被 free() 释放的内存的软件。与其他内存调试器不同,Electric Fence 可以检测读访问和写访问,并能精确定位导致错误的指令。
由于 Electric Fence 库不受 Red Hat 官方支持,您需要自己下载、构建并在您的系统上进行安装。安装后,在生成推理可执行文件时使用“-lefence”选项链接此库。然后只需执行它,就会导致运行时错误并在导致内存访问问题的点停止。您可以使用调试器或上一节中描述的调试打印函数来识别问题所在。