CANN Runtime EE1021 资源创建失败(Resource_Error)错误码排查指南
2026/9/21 19:02:08 网站建设 项目流程

CANN Runtime EE1021 资源创建失败(Resource_Error)错误码排查指南

【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime

导读

EE1021 是 CANN Runtime 在主机(Host)侧创建信号量、线程等系统资源失败时上报的错误码,属于 RTS(Runtime System)错误类别下的资源类错误(Resource_Error)。本文从错误码定义、上报格式、触发源码路径到排查方法逐层展开,帮助开发者在遇到The runtime module failed to create host ... through API ...报错时,快速定位资源瓶颈并完成恢复。

错误码基本信息

EE1021 在 error_code.json 中登记为:

{ "errClass": "RTS Errors", "errTitle": "Resource_Error", "ErrCode": "EE1021", "ErrMessage": "The runtime module failed to create host %s through API %s.", "Arglist": "resource_type, api", "suggestion": { "Possible Cause": "Failed to create resources such as semaphores, locks, or threads due to insufficient system resources.", "Solution": "Stop unnecessary threads and ensure that the required resource is available." } }

该错误码在 error_code_meta.h 中对应的宏定义为:

/* EE1021 - Resource_Error */ X(EE1021, "EE1021", ("resource_type", "api"), "The runtime module failed to create host %s through API %s. ErrorCode=EE1021.\n", DLOG_ERROR)

可以看到 EE1021 携带两个动态参数resource_type(资源类型)和api(失败接口名),并按DLOG_ERROR级别记录日志。日志级别可通过环境变量ASCEND_GLOBAL_LOG_LEVEL控制,相关说明见 env_vars 目录。

错误信息格式解析

文档给出的报错格式如下:

The runtime module failed to create host %s through API %s.

其中占位符含义为:

占位符含义典型取值
%s(第一个)资源类型(resource_type)semaphore(信号量)、thread(线程)、lock(锁)等主机侧资源
%s(第二个)失败的标准接口名(api)sem_initpthread_createpthread_setname_nppthread_join

值得说明的是,在真实的 Runtime 日志输出中,报错文本后还会附带错误码后缀,完整输出形如The runtime module failed to create host semaphore through API sem_init. ErrorCode=EE1021.,便于日志检索时直接用EE1021关键字过滤。日志文件的位置与生成方式可参考 log_ref 目录。

报错示例解读

文档给出的典型报错示例如下:

The runtime module failed to create host semaphore through API sem_init.

这条报错对应 Runtime 内部调用sem_init(实际封装为mmSemInit)初始化信号量失败。结合源码可以还原出真实的触发链路:

  • direct_hwts_engine.cc 中,HWTS 引擎创建回收线程(Recycle Thread)时执行mmSemInit(&recycleThreadSem_, 0U),失败后上报:
const rtError_t error = mmSemInit(&recycleThreadSem_, 0U); if (error != RT_ERROR_NONE) { DELETE_O(recycleThread_); RT_LOG_OUTER_MSG_IMPL(ErrorCode::EE1021, "semaphore", "sem_init"); return RT_ERROR_MEMORY_ALLOCATION; }
  • stars_engine.cc 中,Stars 引擎在CreateRecycleThread中存在完全相同的信号量初始化失败处理逻辑,同样上报EE1021, "semaphore", "sem_init"

这两个引擎都是 Runtime 维护任务回收与线程生命周期的核心组件,说明该错误码出现的位置集中在 Runtime 初始化阶段的后台线程/信号量装配路径上。

可能原因

按照文档与 error_code.json 中suggestion字段的说明,EE1021 的根本原因是系统资源不足导致 Runtime 无法创建信号量、锁或线程等主机侧资源。从源码调用点归纳,常见诱因包括:

  1. 进程/线程数量达到系统上限pthread_create失败时,通常是进程内线程数达到RLIMIT_NPROC限制,或内核threads-max已达上限。
  2. 信号量资源耗尽sem_init返回失败,可能是内核信号量队列或 POSIX 信号量相关资源不足。
  3. 内存不足:创建线程需要分配线程栈,内存耗尽时pthread_create也会失败。
  4. 线程命名失败pthread_setname_np失败虽然不致命(Runtime 仅记录日志后继续),但也会以 EE1021 形式暴露,提示系统或平台对线程名长度等存在限制。

典型触发场景与源码佐证

场景一:线程创建失败(pthread_create)

在 osal.cc 的LocalThread::Start中,Runtime 创建本地线程时先以默认栈大小尝试,失败后会循环增大栈大小重试,重试仍失败则上报 EE1021:

for (uint32_t i = 0U; i < PTHREAD_STACK_SIZE_EXT_MAX_TIME; i++) { error = mmCreateTaskWithThreadAttr(&interThread_, &userBlock_, &threadAttr); if (error == EN_OK) { ... return EN_OK; } threadAttr.stackSize += PTHREAD_STACK_SIZE; } RT_LOG_OUTER_MSG_IMPL(ErrorCode::EE1021, "thread", "pthread_create"); return error;

线程栈大小优先取自设备属性中的pthreadStackSize,未配置时使用系统默认栈(见同文件GetThreadStackSize),这一逻辑说明线程栈分配对系统内存有一定需求。

场景二:线程设置名称失败(pthread_setname_np)

在线程入口函数LocalThread::ThreadProc中,Runtime 调用mmSetThreadName为线程命名,失败时记录:

const int32_t ret = mmSetThreadName(RtPtrToPtr<mmThread*>(&threadHandle), self->name_); if (ret != EN_OK) { RT_LOG_OUTER_MSG_IMPL(ErrorCode::EE1021, "thread", "pthread_setname_np"); }

场景三:线程回收失败(pthread_join)

LocalThread::Join与进程退出路径ThreadGuard::ThreadExit中,mmJoinTask失败也会上报EE1021, "thread", "pthread_join"(osal.cc)。这类失败通常发生在资源紧张导致线程无法正常退出的情况下。

测试用例佐证

单元测试中有专门模拟sem_init失败的用例,例如 aicpu_cust_work_test.cc 中的CreateWorkTest_sem_init_fail

TEST_F(AICPUCusWorkerTEST, CreateWorkTest_sem_init_fail) { MOCKER(sem_init).stubs().will(returnValue(-1)); ... }

该用例通过 mock 使sem_init返回 -1 来验证资源创建失败时的错误处理路径,与 EE1021 的触发条件完全对应,可用于理解失败分支的行为。

错误上报机制简述

EE1021 最终通过RT_LOG_OUTER_MSG_IMPL宏进入日志链路,宏定义位于 base.hpp,其可展开形态将错误码、参数与标准库调用失败信息组合后输出到 Runtime 日志。ErrorCode::EE1021枚举在 rt_log.h 中定义,保证错误码在整个 Runtime 内部以编译期常量形式引用。

排查步骤

当程序运行日志中出现EE1021且伴随sem_initpthread_create等接口名时,建议按以下顺序排查:

  1. 确认错误上下文:在 Runtime 日志中检索EE1021关键字,确认报错时resource_typeapi的具体取值,判断是信号量创建失败还是线程创建失败。
  2. 检查进程线程数限制
    • 查看用户进程/线程上限:ulimit -u
    • 查看内核线程上限:cat /proc/sys/kernel/threads-max
    • 统计当前进程线程数:ps -eLf | grep <进程名> | wc -lps -o nlwp -p <pid>
  3. 检查系统内存:使用free -g观察可用内存是否充足,重点确认是否存在内存泄漏或大页占用导致线程栈分配失败。
  4. 检查信号量相关资源:若报错为sem_init,可结合ipcs -s观察系统中信号量数量是否接近内核限制。
  5. 减少无关负载后复现:停止同一主机上其他不必要的线程密集型进程,缩小问题范围,确认是否为多进程并发触发资源争抢。

解决方法与预防建议

针对文档给出的官方建议"停止不必要的线程,并确保所需资源可用",结合实践可细化为:

  1. 释放或关闭无关进程:结束同一机器上不再使用的后台进程与服务,为 Runtime 腾出线程和内存配额。
  2. 调整线程/进程资源限制:在确认业务安全的前提下,通过ulimit -u提高用户进程上限,或在系统配置中调大kernel.threads-max
  3. 优化应用自身并发模型:多进程场景下控制进程数,避免每个进程都初始化独立 Runtime 实例,减少同时创建的后台线程总数。
  4. 评估内存占用:确保主机内存余量足以支撑 Runtime 各引擎线程(回收线程、监控线程、打印线程等)的栈空间分配,必要时释放缓存或扩容。
  5. 排查线程命名冲突:若报错为pthread_setname_np,检查平台对线程名长度的限制,并避免使用超长或含特殊字符的线程名。

由于 EE1021 属于主机侧资源类错误,其排查核心始终围绕"线程、信号量、内存三类资源是否达到瓶颈"展开,可结合 Runtime 故障排查 与 日志查看说明 进一步定位。

【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询