性能问题故障排除
目录
- 为什么即使将 graph_optimization_level 设置为 ORT_ENABLE_ALL,模型图也未被优化?
- 为什么我的模型在 GPU 上运行比在 CPU 上运行慢?
- 我转换的 TensorFlow 模型很慢——为什么?
- 我看到高延迟变化。
- 我看到 Windows 上的 CPU 使用率很高
以下是评估性能问题时要检查的事项列表
- 您是否启用了所有 图优化?官方发布的包默认启用所有优化,但如果从源代码构建,请检查您的构建中是否启用了这些优化。
- 您是否搜索了先前提交的 GitHub 问题,以查看您的问题是否已被讨论过?请在提交新问题之前执行此操作。
- 如果使用 CUDA 或 TensorRT,您是否安装了正确版本的依赖库?CUDA EP / TensorRT EP
为什么即使将 graph_optimization_level 设置为 ORT_ENABLE_ALL,模型图也未被优化?
来自 IR_VERSION 4 的 ONNX 模型只将出现在图输入中的初始化器视为非常量。这可能会阻止一些图优化,如常量折叠、运算符融合等。如果没有必要覆盖初始化器,请通过使用最新的导出器/转换器重新生成模型,或使用工具 remove_initializer_from_input.py 将初始化器移出图输入。
为什么我的模型在 GPU 上运行比在 CPU 上运行慢?
根据您使用的执行提供者,它可能无法完全支持模型中的所有运算符。回退到 CPU 操作可能会导致性能速度下降。此外,即使某个操作由 CUDA 执行提供者实现,出于性能原因,它也可能不会将该操作分配/放置到 CUDA EP。要查看 ORT 决定的放置情况,请打开详细日志并查看控制台输出。
我转换的 TensorFlow 模型很慢——为什么?
NCHW 和 NHWC 是 4 维张量的两种不同内存布局。
CNN 使用的大多数 TensorFlow 操作都支持 NHWC 和 NCHW 数据格式。TensorFlow 团队建议在 GPU 上 NCHW 更快,但在 CPU 上 NHWC 有时在 TensorFlow 中更快。然而,ONNX 只支持 NCHW。因此,如果原始模型是 NHWC 格式,在模型转换时可能会添加额外的转置。 tensorflow-onnx 转换器确实去除了其中许多转置,但如果这不足以提供帮助,请考虑以 NCHW 格式重新训练模型。
我看到高延迟变化。
在某些平台上,onnxruntime 在推理过程中可能会表现出高延迟变化。这是由 onnxruntime 用于在线程池中并行化任务的常数成本模型引起的。对于每个任务,常数成本模型会计算一个在线程之间并行化的粒度,该粒度在任务执行结束时保持不变。这种方法有时会导致负载不平衡,从而导致高延迟变化。为了缓解这个问题,onnxruntime 提供了一个动态成本模型,可以作为会话选项启用。
sess_options.add_session_config_entry('session.dynamic_block_base', '4')
只要设置为正值,onnxruntime 线程池将以递减的粒度并行化内部任务。具体来说,假设有一个函数期望由线程池运行 N 次,启用动态成本模型后,池中的每个线程都将在
residual_of_N / (dynamic_block_base * num_of_threads)
准备运行时索取任务。因此,在一段时间内,池中的线程更可能实现更好的负载平衡,从而降低延迟变化。
出于同样的原因,动态成本模型也可能在线程更容易被抢占的情况下改善性能。根据我们的测试,目前为止 dynamic_block_base 的最佳配置是 4,它在保持良好性能的同时降低了方差。
我看到 Windows 上的 CPU 使用率很高
据观察,对于拥有超过 64 个逻辑核心的机器,通过让线程池使用无锁任务队列,可以显著降低 CPU 使用率,该队列利用自旋锁而非互斥锁进行同步。无锁任务队列可以通过从源代码构建 onnxruntime 并使用以下标志来启用:
--use_lock_free_queue