文档的一些笔记:
性能调优小工具 ONNX GO Live Tool
这玩意儿有俩docker容器来实现支持,一个优化容器和一起模型转换容器。暂时具体不清楚原理,还没来得及看,后面试试。
什么执行单元(Execution Provider, EP)能够提供最好的性能表现
CPU版本的ONNX Runtime提供了完整的算子支持,因此只要编译过的模型基本都能成功运行。一个要注意的点是为了减少编译的二进制包能够足够小,算子只支持常见的数据类型,如果是一些非常见数据类型,请去提交PR。
CUDA版本的算子并不能完全支持,如果模型中有一部分不支持的算子,将会切换到CPU上去计算,这部分的数据切换是有比较大的性能影响。当然也可以contribute或者提交issue。
对于TRT和CUDA的区别,在同设备上TRT会比CUDA有着更好的性能表现,但是这个状况也局限于特定的模型以及算子是被TRT支持。
性能调优的一些建议
- Shared arena based allocator
通过配置多个session中共享内存区域配置,可以减少内存消耗
- 线程调控
- 如果编译支持OpenMP,那么使用OpenMP的环境变量来控制预测线程数量。
- 如果没有OpenMP支持,使用合适的ORT API来进行操控。
- 当使用并行实行的时候inter op线程并不会受到OpenMP设置的影响,且总是应该使用ORT APIs来进行设置。
默认CPU执行单元的相关设置(MLAS)
默认EP使用了很多旋钮来控制线程数量。举个例子:
- Thread Count
-
sess_options.intra_op_num_threads = 2
控制了运行模型时的线程数量。
- Sequential vs Parallel Execution
-
sess_options.execution_mode = rt.ExecutionMode.ORT_SEQUENTIAL
控制了计算图内部的算子是顺序计算还是并行计算,当一个模型含有多个分支的时候,设置为False会有比较大的性能提升。
- 当
sess_options.execution_mode = rt.ExecutionMode.ORT_PARALLEL
时(即模型内计算图中的并行), 你可以设置 sess_options.inter_op_num_threads 来对并行计算的线程数量进行控制。这里注意是inter不是intra,和Thread Count里面的那个不一样。 -
sess_options.graph_optimization_level = rt.GraphOptimizationLevel.ORT_ENABLE_ALL
图结构优化设置,分为三个level
,Basic
,Extend
和Layout Optimizations
。默认所有的优化都是ENABLE。
MKL_DNN / nGraph执行单元
这俩玩意儿依赖openmp支持来实现并行化,对于这俩需要使用openmp的环境变量来进行性能调整。
- OMP_NUM_THREADS=n
- 控制线程池大小
- OMP_WAIT_POLICY=PASSIVE / ACTIVE
- 线程是否是thread spinning模式(线程调度的一种方式)。
- PASSIVE 吞吐量模式,CPU只有在完成当前任务后被释放。当CPU使用率已经很高了,用这个模式。
- ACTIVE 永远不会释放CPU,会以一个死循环的方式来检查下一个任务是否已经准备好。当你要低时延,用这个模式。