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 library” 来调试这些问题。它帮助您检测两个常见的编程问题:超出 malloc() 分配的内存边界的软件,以及访问已被 free() 释放的内存分配的软件。与其他内存调试器不同,Electric Fence 会检测读访问和写访问,并能精确指出导致错误的指令。
由于 Electric Fence library 未得到 RedHat 的官方支持,您需要自己下载、构建和安装其源代码。安装完成后,在生成推理可执行文件时,使用“-lefence”选项链接此库。然后直接执行它,这将导致运行时错误并停止在引起内存访问问题的地方。您可以使用调试器或上一节描述的调试打印函数来确定位置。