如何强制 ONNX Runtime 单线程执行(OMP_NUM_THREADS 与 intra_op_num_threads)
【免费下载链接】onnxruntimeONNX Runtime: cross-platform, high performance ML inferencing and training accelerator项目地址: https://gitcode.com/GitHub_Trending/on/onnxruntime
当你用 ONNX Runtime 跑推理时,session.run()默认会占用计算机的全部核心。在需要控制 CPU 占用(例如做基准测试、复现性能问题,或部署在核数受限的机器上)时,就需要把它强制到单线程执行。根据 docs/FAQ.md 的说明,具体做法取决于你的 ONNX Runtime 构建是否启用了 OpenMP:
- 构建时启用了 OpenMP:设置环境变量
OMP_NUM_THREADS为1。 - 未启用 OpenMP:把 session options 的
intra_op_num_threads设为1。 - 两种情况下都不要改动
inter_op_num_threads的默认值(本身就是 1)。
FAQ 同时建议:如果你只需要单线程执行,构建 onnxruntime 时干脆不要启用 OpenMP,这样线程行为完全由 session options 决定,不用关心环境变量。该做法从 ONNX Runtime v1.3.0 起支持。
先确认你的构建是否用了 OpenMP
这是选择上面哪条路径的前提。docs/NotesOnThreading.md 说明了 ONNX Runtime 的线程模型:算子内部(intra op)并行可以走 OpenMP 或 ORT 线程池,选择由构建时的--use_openmp开关决定;而算子之间(inter op)的并行始终走 ORT 线程池。也就是说:
- 如果构建带了 OpenMP,仅设置
intra_op_num_threads = 1只能限制 ORT 线程池的分支,OpenMP 侧仍可能起多线程,必须再配合OMP_NUM_THREADS=1; - 如果没带 OpenMP,
intra_op_num_threads直接控制每个算子内部的线程数,设为 1 即为单线程。
判断方法:如果你用的是官方预编译包,以该构建发布说明为准;如果是自己构建的,回看构建命令里是否带有--use_openmp开关即可。
Python:设置 OMP_NUM_THREADS 并创建单线程 Session
FAQ 给出的 Python 示例如下。注意os.environ["OMP_NUM_THREADS"] = "1"必须放在import onnxruntime之前,环境变量在导入时才会被读取:
#!/usr/bin/python3 os.environ["OMP_NUM_THREADS"] = "1" import onnxruntime opts = onnxruntime.SessionOptions() opts.inter_op_num_threads = 1 opts.execution_mode = onnxruntime.ExecutionMode.ORT_SEQUENTIAL ort_session = onnxruntime.InferenceSession('/path/to/model.onnx', sess_options=opts)其中/path/to/model.onnx需要替换成你自己的模型文件路径。示例里同时设置了inter_op_num_threads = 1和execution_mode = ORT_SEQUENTIAL,这与 FAQ 正文"inter_op 默认已是 1"的说法一致——显式写出来只是让单线程意图更清晰。
C++:通过 SessionOptions 限制线程数
C++ 示例同样来自 FAQ。它展示了通过Ort::SessionOptions的 setter 配置线程数(SetIntraOpNumThreads/SetInterOpNumThreads的声明见 onnxruntime_cxx_api.h):
// initialize environment...one environment per process Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "test"); // initialize session options if needed Ort::SessionOptions session_options; session_options.SetInterOpNumThreads(1); #ifdef _WIN32 const wchar_t* model_path = L"squeezenet.onnx"; #else const char* model_path = "squeezenet.onnx"; #endif Ort::Session session(env, model_path, session_options);示例中的squeezenet.onnx是文档自带的演示模型名,换成你自己的模型即可。对应地,未启用 OpenMP 的单线程场景应改为调用session_options.SetIntraOpNumThreads(1);启用 OpenMP 时则同样需要在进程环境里设置OMP_NUM_THREADS=1。
验证:确认确实只有一个线程在执行
ONNX Runtime 没有提供一个直接打印"当前线程数"的开关,文档给出的验证手段是观察资源占用是否不再随核心数增长:
- 用 onnxruntime/test/perftest/README.md 中描述的 perftest 工具对模型跑一次基准,它接受
-x: [intra_op_num_threads]:形式来显式指定节点内并行线程数(0表示自动选择默认值); - 分别以单线程配置和默认配置各跑一轮,在系统监视器中观察 CPU 使用率与线程数:单线程配置下 CPU 占用应停留在约一个核心的水平,而不是打满全部核心。
这是文档可支撑的判断方式:默认配置会用满全部核心,单线程配置下多线程占用消失,即为设置生效。
限制与适用条件
- 单线程强制方案适用于 ONNX Runtime v1.3.0 及以上版本(FAQ 明确说明)。
OMP_NUM_THREADS只在你使用了 OpenMP 构建时才有必要;非 OpenMP 构建下设置它没有意义,此时唯一的开关是intra_op_num_threads。- 不要为了单线程去改动
inter_op_num_threads——它的默认值就是 1,FAQ 明确要求保持不动。 - 如果你的目标只是"单线程执行",文档建议直接从构建层面去掉 OpenMP(构建时不启用 OpenMP 开关),运行时行为会更可预期。
【免费下载链接】onnxruntimeONNX Runtime: cross-platform, high performance ML inferencing and training accelerator项目地址: https://gitcode.com/GitHub_Trending/on/onnxruntime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考