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 后端或 protobuf 中的参考输入和输出来验证 onnx-mlir 的输出。
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 库不受 RedHat 官方支持,因此您需要自行下载、构建和安装源代码。安装完成后,在生成推理可执行文件时使用“-lefence”选项链接此库。然后只需执行它,这将导致运行时错误并在导致内存访问问题的地方停止。您可以使用调试器或上一节中描述的调试打印函数来识别该位置。