DEBUG.WIKI
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
雨云;给项目一台云服务器
RackNerd;$21.99/年 · 1GB KVM

ONNX Runtime 启动时反复报 pthread_setaffinity_np error 22,线程数该设在哪里?

pthread_setaffinity_np error 22 指向 CPU 线程绑定。把 intra_op_num_threads 传入实际创建 session 的配置,保留原 provider 和 CPU 限制,再检查日志、结果与负载表现。

ONNX Runtime 启动时反复报 pthread_setaffinity_np error 22,线程数该设在哪里?

这条日志指向 CPU 线程绑定,先检查创建 ONNX Runtime session 的代码:

pthread_setaffinity_np failed
error code: 22 error msg: Invalid argument

即使应用使用 GPU 执行提供程序,也不能仅凭这条日志认定 CUDA 出了问题。ONNX Runtime 官方仓库在 2025 年 7 月的一则 TensorRT RTX 讨论中记录了同样的错误;该报告没有给出足以确定发行版本的信息,不能据此划出某个版本必现的范围。原始报告

先确认应用有没有使用默认线程配置

ONNX Runtime 文档说明:intra_op_num_threads 未设置或为 0 时,运行时会按物理核心创建计算线程,并给额外线程设置亲和性。显式指定线程数量后,默认的自动绑核不再应用到这些线程。线程管理说明

容器、受限 CPU 集合或特殊 CPU 拓扑值得检查,但错误本身还不足以确认是哪一种。可以在应用所在环境读取进程实际允许使用的 CPU:

import os
import onnxruntime as ort

print("ONNX Runtime:", ort.__version__)
print("logical CPU count:", os.cpu_count())
if hasattr(os, "sched_getaffinity"):
    print("allowed CPUs:", sorted(os.sched_getaffinity(0)))

允许使用的 CPU 集合与容器的 CPU 时间配额也不是同一概念。保留这些信息,再检查应用或框架是否额外写入了 session.intra_op_thread_affinities。

把设置传给真正创建 session 的地方

可先用单线程做一个小范围对照。在原有代码创建 session 之前添加:

import onnxruntime as ort

session_options = ort.SessionOptions()
session_options.intra_op_num_threads = 1

# model_path 和 providers 沿用应用原来的值。
session = ort.InferenceSession(
    model_path,
    sess_options=session_options,
    providers=providers,
)

这是代码片段,model_path 和 providers 需要来自应用原配置。不要为了套用示例把 GPU provider 换成 CPU,也不要在 session 已创建后才修改另一个 options 对象。

如果框架代为创建 session,应通过它实际支持的配置入口传入。只在外层新建一个无人使用的 SessionOptions 不会改变行为。原程序还有其他 session 选项时,应在保留那些选项的基础上改线程数。

显式自定义的亲和性配置是另一条路径;若应用已经配置了它,需要单独检查,而不能期待设置线程数覆盖所有绑核逻辑。修改 inter_op_num_threads 也不能代替这里的 intra-op 设置。

日志消失后还要确认什么?

重新创建 session,用原来的固定输入完成一次推理,确认结果与原流程一致。若 error 22 消失,再在分配到的 CPU 资源内测试线程数与并发组合。单线程只是排查起点,不能保证它的吞吐或延迟最佳。

如果应用仍然退出,继续看后面的异常和退出状态。ONNX Runtime 的相关源码在绑核失败处记录错误后仍会进入线程执行函数,因此这条日志本身不能证明它就是最终退出原因。线程实现

保留容器的 CPU 限制,不必为消除日志开放全部宿主机核心或提升容器权限。