
Kernel 模块架构【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime1. 模块概述功能介绍Kernel 模块负责管理内核二进制的注册、查找和执行Kernel 维护内核元信息名称、偏移、参数等。设计目标提供内核注册和查找机制管理内核元信息支持内核二进制加载到设备支持 AI CoreAI Cube、AI Vector、MIXAI Cube 和 AI Vector 混合、AICPU 多种算子注册支持按核函数名称Function Name/核函数标识Function Entry两种查找方式2. 使用场景与对外接口2.1 使用场景场景一二进制注册从文件aclrtBinHandle binHandle nullptr; aclrtBinaryLoadFromFile(binPath, nullptr, binHandle); // 内部路径: rtsBinaryLoadFromFile → BinaryLoader::Load → ElfProgram::Register → UnifiedKernelRegister场景二二进制注册从内存aclrtBinHandle binHandle nullptr; aclrtBinaryLoadFromData(data, length, nullptr, binHandle); // 内部路径: rtsBinaryLoadFromData → BinaryLoader::Load → ElfProgram::Register场景三内核查找与执行aclrtFuncHandle funcHandle nullptr; aclrtBinaryGetFunction(binHandle, kernelName, funcHandle); aclrtLaunchKernel(funcHandle, numBlocks, argsData, argsSize, stream);场景四内核查找按核函数标识aclrtFuncHandle funcHandle nullptr; aclrtBinaryGetFunctionByEntry(binHandle, funcEntry, funcHandle);2.2 对外接口接口对应 rt 调用说明aclrtCreateBinary()本地 new rtDevBinary_t创建二进制描述对象aclrtDestroyBinary()本地 delete销毁二进制描述对象aclrtBinaryLoad()rtBinaryLoadWithoutTilingKey()注册二进制旧接口无 tiling keyaclrtBinaryUnLoad()rtBinaryUnLoad()卸载二进制aclrtBinaryLoadFromFile()rtsBinaryLoadFromFile()从文件注册二进制aclrtBinaryLoadFromData()rtsBinaryLoadFromData()从内存注册二进制aclrtBinaryGetFunction()rtsFuncGetByName()按名称获取内核函数aclrtBinaryGetFunctionByEntry()rtsFuncGetByEntry()按核函数标识获取内核函数aclrtBinaryGetDevAddress()rtsBinaryGetDevAddress()获取二进制设备侧地址aclrtBinaryGetGlobal()rtBinaryGetGlobal()获取全局符号地址aclrtBinarySetExceptionCallback()rtBinarySetExceptionCallback()设置异常回调aclrtLaunchKernel()rtLaunchKernelByFuncHandleV3()执行内核aclrtLaunchKernelV2()rtsLaunchKernelWithDevArgs()执行内核V2aclrtLaunchKernelWithConfig()rtsLaunchKernelWithConfig()执行内核带配置aclrtLaunchKernelWithHostArgs()rtsLaunchKernelWithHostArgs()执行内核Host 参数aclrtLaunchKernelWithArgsArray()rtLaunchKernelWithArgsArray()执行内核参数数组3. 架构总览3.1 整体设计思路BinaryLoader内核注册入口从文件或内存加载二进制并创建 Program。Program管理内核二进制和查找维护名称映射和 tilingKey 有序表两个查找机制。ElfProgram 解析 ELF 并注册内核PlainProgram 注册 CPU 内核。Kernel维护内核元信息通过所属 Program 的基地址直接计算设备侧函数地址。KernelTable全局 stub→Kernel 有序映射表二分查找支持按 Program 批量卸载。设备侧加载通过 Program::Load2Device → Runtime::BinaryLoad 完成在 aclrtBinaryGetFunction 内部触发。3.2 架构分层图3.3 核心模块交互图4. 详细设计4.1 核心流程二进制注册流程流程步骤说明BinaryLoader 判断 CPU/非 CPU 路径通过isLoadCpu_标志区分非 CPU 路径LoadProgram 创建 ElfProgram → Register 保存二进制 → ParserBinary 解析 ELF 符号和属性 → UnifiedKernelRegister 执行两步注册UnifiedKernelRegister 先调用 RegisterAllKernelCommon 按名称注册到kernelNameMap_再遍历所有 Kernel 按 tilingKey 排序插入KernelTable_CPU 路径创建 PlainProgram根据模式加载 CPU 算子信息并注册关键代码// 文件位置src/runtime/core/src/kernel/program.cc rtError_t ElfProgram::UnifiedKernelRegister() { rtError_t error RegisterAllKernelCommon(); ERROR_RETURN(error, register all kernel failed, retCode%#x., static_castuint32_t(error)); const std::mapstd::string, Kernel * kernelNameMap GetKernelNameMap(); for (auto iter kernelNameMap.begin(); iter ! kernelNameMap.end(); iter) { Kernel* kernelObj iter-second; if (kernelObj-GetFunctionEntryType() KernelFunctionEntryType::KERNEL_TYPE_NOT_SUPPORT_FUNCTION_ENTRY) { continue; } bool isRepeated false; error AllKernelAdd(kernelObj, isRepeated); ERROR_RETURN(error, add kernel to tilingKey table failed, kernel_name%s, tilingKey%llu., kernelObj-Name_().c_str(), kernelObj-TilingKey()); } return RT_ERROR_NONE; }ELF 解析流程流程步骤说明读 ELF 文件头确认是合法 64-bit 格式遍历 ELF 各 Section提取代码段位置和大小、解析每个内核的元信息名称、偏移、长度、funcType、funcEntryType 等、获取 so_name将解析结果组装为 RtKernel 数组每个 RtKernel 包含一个内核的全部描述信息根据 ELF 头的 e_machine 设置默认内核类型AICore/AICPU记录 soName 和 metadata关键代码// 文件位置src/runtime/core/src/kernel/program.cc rtError_t ElfProgram::ParserBinary() { elfData_-obj_size binarySize_; kernels_ ProcessObject(RtPtrToPtrchar_t *(binary_), elfData_); if (elfData_-elf_header.e_machine 183U) { SetDefaultKernelAttrType(RT_KERNEL_ATTR_TYPE_AICPU); } else { SetDefaultKernelAttrType(RT_KERNEL_ATTR_TYPE_AICORE); } SetMachine(elfData_-elf_header.e_machine); SetStackSize(elfData_-stackSize); soName_ elfData_-so_name; }// 文件位置src/runtime/core/src/kernel/program.cc void ElfProgram::SetKernelAttribute(const RtKernel *kernel, Kernel *kernelObj) { const RtKernelMetaInfo *metaInfo (kernel-metaInfo); kernelObj-SetKernelLength1(kernel-length); kernelObj-SetKernelVfType_(metaInfo-kernelVfType); kernelObj-SetFuncType(metaInfo-funcType); kernelObj-SetTaskRation(metaInfo-taskRation); kernelObj-SetFunctionEntryType(metaInfo-funcEntryType); kernelObj-SetParamTotalSize(metaInfo-paramTotalSize); }内核查找流程流程步骤说明按名称查找aclrtBinaryGetFunction通过rtsFuncGetByName→Program::GetKernelByName在kernelNameMap_中直接查找按核函数标识查找aclrtBinaryGetFunctionByEntry通过rtsFuncGetByEntry→Program::AllKernelLookup在KernelTable_有序数组中二分查找 tilingKey内核加载到设备流程流程步骤说明设备侧加载在 aclrtBinaryGetFunction 内部通过 CopySoAndNameToCurrentDevice 触发。Program::Load2Device 调用 Runtime::BinaryLoad 完成实际拷贝分配设备内存优先使用 KernelMemoryPool 内存池、4K 地址对齐ARM ADRP 指令要求、H2D 拷贝、记录 baseAddr/baseAddrAlign。内核执行流程流程步骤说明aclrtLaunchKernel 将 funcHandleKernel*和参数传递给 rtLaunchKernelByFuncHandleV3ApiImpl::LaunchKernel 获取设备侧函数地址Kernel::GetFunctionDevAddr 通过 baseAddrAlign offset 直接计算 kernelPc1/kernelPc2StreamLaunchKernelV2 从 Stream 任务池分配 TaskInfoAicTaskInit 初始化内核类型、blockDim、qos 等信息通过 ArgManager 将内核参数加载到设备ArgPool 或 H2D 拷贝填充 AicTaskInfo 字段kernel、progHandle、funcAddr构造 SQE 提交到设备 SQ硬件执行内核关键代码// 文件位置src/runtime/core/src/launch/aix_starsv2.cc rtError_t StreamLaunchKernelV2(Kernel *kernel, const uint32_t coreDim, Stream *stm, const rtStreamLaunchKernelV2ExtendArgs_t *extendAgrs, const bool isLaunchVec) { Program * const prog kernel-Program_(); // 获取设备侧函数地址 error kernel-GetFunctionDevAddr(kernelPc1, kernelPc2); // 分配 TaskInfo error AllocTaskInfoForCapture(kernelTask, stm, pos, dstStm, 1U, true); // 初始化内核任务 AicTaskInit(kernelTask, kernelAttrType, static_castuint16_t(coreDim), extendAgrs-taskCfg, false); // 加载参数 error static_castDavidStream *(dstStm)-LoadArgsInfo(argsInfo, useArgPool, result); // 填充任务信息 aicTask-kernel const_castKernel *(kernel); aicTask-progHandle prog; aicTask-funcAddr kernelPc1; aicTask-funcAddr1 kernelPc2; // 提交到设备 error DavidSendTask(kernelTask, dstStm); }4.2 核心机制详解Kernel 内核元信息设计思想Kernel 维护内核全部元信息支持 CPU 和非 CPU 两种注册类型每种类型的构造器不同。非 CPU Kernel 由 ElfProgram 在解析 ELF 时创建CPU Kernel 由 PlainProgram 在注册 CPU 算子时创建。重点字段按功能分组功能分组字段类型含义基础标识program_Program*所属程序name_string内核名称tilingKey_uint64_tTiling KeykernelAttrType_rtKernelAttrType内核类型AIC/AIV/MIXAI Cube 和 AI Vector 混合/AICPUkernelRegisterType_KernelRegisterType注册类型CPU/非 CPU设备地址offset1_/offset2_uint32_t函数偏移 1/偏移 2stubFun_const void*stub 函数地址funcEntryType_KernelFunctionEntryType核函数标识类型TilingKey/FunctionEntry执行参数mixType_uint8_t混合类型AICAIV 模式taskRation_uint32_tAIC:AIV 任务配额schedMode_uint32_t调度模式length1_/length2_uint32_t内核代码长度CPU 算子cpuOpType_stringCPU 算子类型cpuKernelSo_stringCPU SO 名称cpuFunctionName_stringCPU 函数名称DFX/ProfilingdfxAddr_/dfxSize_void*/uint16_tDFX 调试信息nameId_uint64_t名称哈希 ID用于 ProfilingisSupportOverFlow_bool是否支持溢出检测核心方法方法功能GetFunctionDevAddr()获取设备侧函数地址baseAddrAlign offsetGetNameId()获取内核名称哈希 ID首次调用时计算并缓存SetKernelAttribute()在 ElfProgram 注册时批量设置内核属性KernelTable 内核映射表设计思想采用有序数组 二分查找实现高效 stub→Kernel 映射同时维护多个辅助映射表支持不同查找场景。重点字段字段类型含义kernelArr_rtKernelArr_t*有序数组按 stub 地址排序支持二分查找kernelMapLock_SpinLock并发保护锁kernelInfoExtMap_mapstring, Kernel*kernelInfoExt→Kernel 映射扩展信息查找invKernelMap_mapstring, const void*name→stub 反向查找programStubMultiMap_multimapProgram*, const void*Program→stubs 映射卸载时按 Program 批量删除重点方法方法功能Add()注册内核二分查找定位 → ArrayInsert 插入有序数组 → 更新辅助映射Lookup()stub 查找二分查找 → 返回 Kernel*同时检查 Program 是否已卸载RemoveAll()按 Program 批量卸载遍历 programStubMultiMap → 二分查找定位 → memmove 删除 → 更新辅助映射Program 继承体系设计思想Program 基类定义公共接口和二进制管理逻辑PlainProgram 和 ElfProgram 分别实现 CPU 算子简单二进制和 ELF 格式内核的管理。Program 基类重点字段字段类型含义binary_/binarySize_void*/uint64_t二进制数据及大小KernelTable_rtKernelArray_t*Program 内 tilingKey→Kernel 有序表kernelNameMap_mapstring, Kernel*name→Kernel 映射progId_uint32_t程序 IDprogType_uint32_t程序类型PLAIN/ELFbaseAddr_[]/baseAddrAlign_[]void*[]各设备上的二进制基地址isNewBinaryLoadFlow_bool新注册流程标志Program 基类核心方法方法功能Register()保存二进制数据 → ParserBinary → AddProgramToPoolGetKernelByName()按名称从 kernelNameMap_ 查找AllKernelLookup()按 tilingKey 从 KernelTable_ 二分查找Load2Device()通过 Runtime::BinaryLoad 将二进制加载到设备在 aclrtBinaryGetFunction 内部触发BuildTilingTbl()/BuildTilingTblForDavid()构建 Tiling 表供任务下发PlainProgramCPU 算子RegisterCpuKernel()从 JSON 解析的 CpuKernelInfo 批量注册 CPU 内核RegisterSingleCpuKernel()单独注册单个 CPU 内核含设备侧名称存储ElfProgramELF 内核ParserBinary()解析 ELF 格式提取内核符号和属性UnifiedKernelRegister()统一注册流程先 nameMap 再 KernelTableRegisterAllKernelCommon()遍历 ELF kernels按名称创建 Kernel 并注册到 kernelNameMap_BinaryLoader 二进制加载器功能描述BinaryLoader 是内核注册的入口组件负责从文件或内存加载二进制数据并创建对应的 Program 对象。它区分 CPU 算子和非 CPU 算子两种加载路径支持多种加载选项。核心方法功能方法功能Load()主入口解析加载选项后分发到 LoadCpu 或 LoadNonCpuLoadNonCpu()非 CPU 路径LoadProgram → UnifiedKernelRegisterLoadCpu()CPU 路径根据 isLoadFromFile 分发到 LoadCpuKernelFromFile 或 LoadCpuKernelFromDataLoadFromFile()/LoadFromData()创建 ElfProgram调用 Register ParseKernelJsonFileParseLoadOptions()解析加载选项Magic、CPU Kernel ModeCPU 注册三种模式Mode 0仅加载 JSON 文件自研算子只需要 JSON 描述Mode 1加载 SO JSON 文件自定义算子需要 SO 和 JSONMode 2从内存数据加载Data 模式通过 hash 生成 SO 名称Module 模块管理注意Module 仅用于旧 rtBinaryLoad 流程aclrt 新流程aclrtBinaryLoadFromFile/Data不使用 Module。aclrt 流程的设备侧加载由 Runtime::BinaryLoad 完成内核地址由 Kernel::GetFunctionDevAddr 直接计算。功能介绍Module 将 Program 的二进制数据加载到设备侧内存提供内核函数地址查询。核心职责包括设备侧内存分配支持 KernelMemoryPool 内存池、4K 地址对齐ARM ADRP 指令要求、H2D 数据拷贝、CPU 算子的 kernelNames/soNames 设备侧存储。核心方法功能方法功能Load(prog)加载 Program 到设备分配内存 → 4K 对齐 → H2D 拷贝 → 记录地址GetFunction(kernel)计算内核函数地址baseAddrAlign offsetGetPrefetchCnt(kernel)计算 ICache 预取计数其他子模块职责arg_loader/参数从 Host 侧加载到 Device 侧的机制。UbArgLoader 使用 UB 缓存池UmaArgLoader 支持 PCIE BAR 和多种分配策略StarsArgManager 是流级参数管理基类派生出 UbArgManage/PcieArgManageargs/参数格式转换与分配。ArgsHandleAllocator 管理 RtArgsHandle 内存ParaConvertor 实现 aclrt 新老参数格式适配elf.hpp / elf.ccELF 格式解析。ProcessObject 解析 ELF 文件提取内核符号RtKernel/RtKernelMetaInfo 描述内核元信息GetKernelTlvInfo 解析 TLV 格式属性kernel_utils.hpp / cc内核任务参数计算工具。ComputeRatio 计算混合执行配额ConvertTaskType/GetKernelTaskParams 提取任务参数program_common.hpp / ccCPU 算子属性设置辅助。SetCpuKernelAttr 统一设置 CPU Kernel 的 SO/FuncName/OpType 属性4.3 模块职责划分模块职责位置Kernel内核元信息管理支持 CPU/非 CPU 类型inc/kernel/kernel.hppKernelTablestub→Kernel 有序映射表二分查找inc/kernel/kernel.hppProgram程序管理基类二进制数据 内核查找inc/kernel/program.hppPlainProgramCPU 算子程序管理inc/kernel/program.hppElfProgramELF 内核程序管理 解析inc/kernel/program.hppBinaryLoader二进制加载入口CPU/非 CPU 注册src/kernel/binary_loader.hppModule设备侧加载仅旧 rtBinaryLoad 流程inc/kernel/module.hppElfELF 格式解析inc/kernel/elf.hppKernelUtils内核任务参数计算src/kernel/kernel_utils.hppProgramCommonCPU 算子属性辅助src/kernel/program_common.hppArgLoader参数 H2D 加载机制src/kernel/arg_loader/Args参数格式转换与分配src/kernel/args/4.4 核心数据结构5. 关键文件索引模块文件路径核心内容Kernel 核心类src/runtime/core/inc/kernel/kernel.hppKernel 类定义 KernelTable 类定义Kernel 实现src/runtime/core/src/kernel/kernel.ccKernel KernelTable 实现Programsrc/runtime/core/inc/kernel/program.hppProgram/PlainProgram/ElfProgram 定义Program 实现src/runtime/core/src/kernel/program.ccProgram 三类实现Modulesrc/runtime/core/inc/kernel/module.hppModule 类定义仅旧 rtBinaryLoad 流程Module 实现src/runtime/core/src/kernel/module.ccModule::Load 等实现仅旧 rtBinaryLoad 流程BinaryLoadersrc/runtime/core/src/kernel/binary_loader.hppBinaryLoader 类定义BinaryLoader 实现src/runtime/core/src/kernel/binary_loader.ccCPU/非 CPU 加载路径ELF 解析src/runtime/core/inc/kernel/elf.hppELF 数据结构定义ELF 实现src/runtime/core/src/kernel/elf.ccProcessObject 等解析函数KernelUtilssrc/runtime/core/src/kernel/kernel_utils.hpp工具函数声明KernelUtils 实现src/runtime/core/src/kernel/kernel_utils.cc工具函数实现ProgramCommonsrc/runtime/core/src/kernel/program_common.hppCPU 辅助函数声明ProgramCommon 实现src/runtime/core/src/kernel/program_common.ccSetCpuKernelAttr 实现ArgLoadersrc/runtime/core/src/kernel/arg_loader/参数加载机制Argssrc/runtime/core/src/kernel/args/参数转换与分配C 接口层src/runtime/api/api_c_kernel.ccrt 内核外部接口aclrt 实现src/acl/aclrt_impl/kernel.cppaclrt 内核接口实现本模块文档基于源码src/runtime/core/src/kernel/分析。【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考