Kernel 模块架构
1. 模块概述
- 功能介绍:Kernel 模块负责管理内核二进制的注册、查找和执行,Kernel 维护内核元信息(名称、偏移、参数等)。
- 设计目标:
- 提供内核注册和查找机制
- 管理内核元信息
- 支持内核二进制加载到设备
- 支持 AI Core(AI Cube、AI Vector)、MIX(AI 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 key) |
aclrtBinaryUnLoad() |
rtBinaryUnLoad() |
卸载二进制 |
aclrtBinaryLoadFromFile() |
rtsBinaryLoadFromFile() |
从文件注册二进制 |
aclrtBinaryLoadFromData() |
rtsBinaryLoadFromData() |
从内存注册二进制 |
aclrtBinaryGetFunction() |
rtsFuncGetByName() |
按名称获取内核函数 |
aclrtBinaryGetFunctionByEntry() |
rtsFuncGetByEntry() |
按核函数标识获取内核函数 |
aclrtBinaryGetDevAddress() |
rtsBinaryGetDevAddress() |
获取二进制设备侧地址 |
aclrtBinaryGetGlobal() |
rtBinaryGetGlobal() |
获取全局符号地址 |
aclrtBinarySetExceptionCallback() |
rtBinarySetExceptionCallback() |
设置异常回调 |
aclrtLaunchKernel() |
rtLaunchKernelByFuncHandleV3() |
执行内核 |
aclrtLaunchKernelV2() |
rtsLaunchKernelWithDevArgs() |
执行内核(V2) |
aclrtLaunchKernelWithConfig() |
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 架构分层图
graph TB
subgraph API["acl 接口层"]
aclBinaryLoad["aclrtBinaryLoadFromFile<br/>aclrtBinaryLoadFromData"]
aclGetFunc["aclrtBinaryGetFunction<br/>aclrtBinaryGetFunctionByEntry"]
aclLaunch["aclrtLaunchKernel<br/>aclrtLaunchKernelV2"]
end
subgraph KernelCore["Kernel 核心层"]
BinaryLoader["BinaryLoader<br/>二进制加载器"]
Program["Program<br/>PlainProgram / ElfProgram<br/>程序管理 + 内核查找"]
Kernel["Kernel<br/>内核元信息"]
KernelTable["KernelTable<br/>stub→Kernel 映射"]
end
subgraph DeviceLayer["设备层"]
DevMem["设备内存<br/>Runtime::BinaryLoad"]
DevAddr["设备侧函数地址"]
end
aclBinaryLoad --> BinaryLoader --> Program
aclGetFunc --> Program
aclLaunch --> Kernel --> DevAddr
Program --> Kernel
Program --> DevMem
KernelTable --> Kernel
Kernel --> DevAddr
3.3 核心模块交互图
sequenceDiagram
participant App as 应用程序
participant acl as acl API
participant Api as Api
participant BL as BinaryLoader
participant Program as ElfProgram
participant Kernel as Kernel
participant Runtime as Runtime
participant Device as Device
rect rgb(230,245,255)
Note over App,Device: 二进制注册阶段
App->>acl: aclrtBinaryLoadFromFile(binPath)
acl->>Api: rtsBinaryLoadFromFile()
Api->>BL: BinaryLoader::Load()
BL->>Program: new ElfProgram + Register()
Program->>Program: ParserBinary() 解析 ELF
Program->>Kernel: new Kernel(name, tilingKey, program, kernelAttrType, offset)
Program->>Kernel: SetKernelAttribute(elfKernelInfo, kernelObj) 设置内核元信息
Program->>Program: KernelNameMapAdd(kernelObj) 加入名称映射
Program->>Program: AllKernelAdd<br/>按 tilingKey 排序插入 KernelTable_
Program-->>Api: progHandle
end
rect rgb(255,240,230)
Note over App,Device: 内核查找 + 设备加载阶段
App->>acl: aclrtBinaryGetFunction(handle, name)
acl->>Api: rtsFuncGetByName()
Api->>Program: GetKernelByName(name)
Program->>Program: CopySoAndNameToCurrentDevice()
Program->>Runtime: Load2Device → Runtime::BinaryLoad
Runtime->>Device: 分配设备内存 + H2D 拷贝
Runtime-->>Program: baseAddrAlign
Program-->>Api: Kernel*
end
sequenceDiagram
participant App as 应用程序
participant acl as acl API
participant Api as ApiImpl
participant Kernel as Kernel
participant Stream as Stars Stream
participant Device as Device
rect rgb(230,255,230)
Note over App,Device: 内核执行阶段
App->>acl: aclrtLaunchKernel(funcHandle, numBlocks, args, stream)
acl->>Api: LaunchKernel(kernel*, numBlocks, argsInfo, stream)
Api->>Kernel: GetFunctionDevAddr(kernelPc1, kernelPc2)
Note over Kernel: baseAddrAlign + offset → 计算设备侧地址
Api->>Stream: AllocTaskInfo + AicTaskInit [分配并初始化任务]
Api->>Stream: LoadArgsInfo [通过 ArgManager 加载内核参数到设备]
Api->>Stream: 构造 SQE + 提交到设备
Stream->>Device: SQE 写入 SQ → 硬件执行
end
4. 详细设计
4.1 核心流程
二进制注册流程
flowchart TD
A[aclrtBinaryLoadFromFile] --> B[BinaryLoader::Load]
B --> C{isLoadCpu_?}
C -->|否| D[LoadNonCpu → LoadProgram]
C -->|是| E[LoadCpu → PlainProgram + RegisterCpuKernel]
D --> F[ElfProgram::Register]
F --> G[ParserBinary 解析 ELF]
G --> H[UnifiedKernelRegister]
H --> I[RegisterAllKernelCommon<br/>按名称注册 Kernel]
I --> J[AllKernelAdd<br/>按 tilingKey 排序插入]
J --> K[返回 Program handle]
E --> K
流程步骤说明:
- 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_cast<uint32_t>(error));
const std::map<std::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 解析流程
flowchart TD
A[ParserBinary 入口] --> B[GetFileHeader<br/>读 ELF 头,确认 64-bit 格式]
B --> C[ProcessSymbolTable<br/>解析符号表]
C --> D[遍历 ELF Section]
D --> E1[提取代码段<br/>text_offset / text_size]
D --> E2[解析内核元信息<br/>ParseKernelMetaData]
D --> E3[获取动态链接信息<br/>so_name 等]
E1 & E2 & E3 --> F[组装 RtKernel 数组<br/>GetKernels + UpdateKernelsInfo]
F --> G[设置内核类型<br/>e_machine → AICore/AICPU]
G --> H[记录 soName / metadata<br/>返回 kernels_]
流程步骤说明:
- 读 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(RtPtrToPtr<char_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);
}
内核查找流程
flowchart TD
A[aclrtBinaryGetFunction] --> B[rtsFuncGetByName]
B --> C[Program::GetKernelByName]
C --> D{kernelNameMap_ 查找}
D -->|找到| E[返回 Kernel*]
D -->|未找到| F[返回 nullptr]
G[aclrtBinaryGetFunctionByEntry] --> H[rtsFuncGetByEntry]
H --> I[Program::AllKernelLookup]
I --> J{KernelTable_ 二分查找}
J -->|找到| K[返回 Kernel*]
J -->|未找到| L[返回 nullptr]
流程步骤说明:
- 按名称查找(
aclrtBinaryGetFunction):通过rtsFuncGetByName→Program::GetKernelByName在kernelNameMap_中直接查找 - 按核函数标识查找(
aclrtBinaryGetFunctionByEntry):通过rtsFuncGetByEntry→Program::AllKernelLookup在KernelTable_有序数组中二分查找 tilingKey
内核加载到设备流程
flowchart TD
A[aclrtBinaryGetFunction] --> B[Runtime::BinaryGetFunctionByName]
B --> C[CopySoAndNameToCurrentDevice]
C --> D[Load2Device]
D --> E[Runtime::BinaryLoad]
E --> F[DevMemAlloc - KernelMemoryPool]
F --> G[4K 地址对齐 - ARM ADRP]
G --> H[H2D 拷贝二进制]
H --> I[SetBinBaseAddr/SetBinAlignBaseAddr]
流程步骤说明:设备侧加载在 aclrtBinaryGetFunction 内部通过 CopySoAndNameToCurrentDevice 触发。Program::Load2Device 调用 Runtime::BinaryLoad 完成实际拷贝:分配设备内存(优先使用 KernelMemoryPool 内存池)、4K 地址对齐(ARM ADRP 指令要求)、H2D 拷贝、记录 baseAddr/baseAddrAlign。
内核执行流程
flowchart TD
A[aclrtLaunchKernel] --> B[rtLaunchKernelByFuncHandleV3]
B --> C[ApiImpl::LaunchKernel]
C --> D[Kernel::GetFunctionDevAddr]
D --> E[baseAddrAlign + offset → kernelPc1/kernelPc2]
C --> F[StreamLaunchKernelV2]
F --> G[AllocTaskInfoForCapture<br/>分配 TaskInfo]
G --> H[AicTaskInit<br/>初始化内核任务信息]
H --> I[LoadArgsInfo<br/>ArgManager 加载内核参数到设备]
I --> J[填充 AicTaskInfo<br/>funcAddr=kernelPc1, progHandle]
J --> K[构造 SQE + 提交到设备 SQ]
K --> L[硬件执行内核]
流程步骤说明:
- aclrtLaunchKernel 将 funcHandle(Kernel*)和参数传递给 rtLaunchKernelByFuncHandleV3
- ApiImpl::LaunchKernel 获取设备侧函数地址:Kernel::GetFunctionDevAddr 通过 baseAddrAlign + offset 直接计算 kernelPc1/kernelPc2
- StreamLaunchKernelV2 从 Stream 任务池分配 TaskInfo,AicTaskInit 初始化内核类型、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_cast<uint16_t>(coreDim), extendAgrs->taskCfg, false);
// 加载参数
error = static_cast<DavidStream *>(dstStm)->LoadArgsInfo(argsInfo, useArgPool, &result);
// 填充任务信息
aicTask->kernel = const_cast<Kernel *>(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_t | Tiling Key | |
kernelAttrType_ |
rtKernelAttrType | 内核类型(AIC/AIV/MIX(AI Cube 和 AI Vector 混合)/AICPU) | |
kernelRegisterType_ |
KernelRegisterType | 注册类型(CPU/非 CPU) | |
| 设备地址 | offset1_/offset2_ |
uint32_t | 函数偏移 1/偏移 2 |
stubFun_ |
const void* | stub 函数地址 | |
funcEntryType_ |
KernelFunctionEntryType | 核函数标识类型(TilingKey/FunctionEntry) | |
| 执行参数 | mixType_ |
uint8_t | 混合类型(AIC+AIV 模式) |
taskRation_ |
uint32_t | AIC:AIV 任务配额 | |
schedMode_ |
uint32_t | 调度模式 | |
length1_/length2_ |
uint32_t | 内核代码长度 | |
| CPU 算子 | cpuOpType_ |
string | CPU 算子类型 |
cpuKernelSo_ |
string | CPU SO 名称 | |
cpuFunctionName_ |
string | CPU 函数名称 | |
| DFX/Profiling | dfxAddr_/dfxSize_ |
void*/uint16_t | DFX 调试信息 |
nameId_ |
uint64_t | 名称哈希 ID(用于 Profiling) | |
isSupportOverFlow_ |
bool | 是否支持溢出检测 |
核心方法:
| 方法 | 功能 |
|---|---|
GetFunctionDevAddr() |
获取设备侧函数地址(baseAddrAlign + offset) |
GetNameId() |
获取内核名称哈希 ID(首次调用时计算并缓存) |
SetKernelAttribute() |
在 ElfProgram 注册时批量设置内核属性 |
KernelTable 内核映射表
设计思想:采用有序数组 + 二分查找实现高效 stub→Kernel 映射,同时维护多个辅助映射表支持不同查找场景。
重点字段:
| 字段 | 类型 | 含义 |
|---|---|---|
kernelArr_ |
rtKernelArr_t* | 有序数组(按 stub 地址排序),支持二分查找 |
kernelMapLock_ |
SpinLock | 并发保护锁 |
kernelInfoExtMap_ |
map<string, Kernel*> | kernelInfoExt→Kernel 映射(扩展信息查找) |
invKernelMap_ |
map<string, const void*> | name→stub 反向查找 |
programStubMultiMap_ |
multimap<Program*, 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_ |
map<string, Kernel*> | name→Kernel 映射 |
progId_ |
uint32_t | 程序 ID |
progType_ |
uint32_t | 程序类型(PLAIN/ELF) |
baseAddr_[]/baseAddrAlign_[] |
void*[] | 各设备上的二进制基地址 |
isNewBinaryLoadFlow_ |
bool | 新注册流程标志 |
Program 基类核心方法:
| 方法 | 功能 |
|---|---|
Register() |
保存二进制数据 → ParserBinary → AddProgramToPool |
GetKernelByName() |
按名称从 kernelNameMap_ 查找 |
AllKernelLookup() |
按 tilingKey 从 KernelTable_ 二分查找 |
Load2Device() |
通过 Runtime::BinaryLoad 将二进制加载到设备(在 aclrtBinaryGetFunction 内部触发) |
BuildTilingTbl()/BuildTilingTblForDavid() |
构建 Tiling 表供任务下发 |
PlainProgram(CPU 算子):
RegisterCpuKernel():从 JSON 解析的 CpuKernelInfo 批量注册 CPU 内核RegisterSingleCpuKernel():单独注册单个 CPU 内核,含设备侧名称存储
ElfProgram(ELF 内核):
ParserBinary():解析 ELF 格式,提取内核符号和属性UnifiedKernelRegister():统一注册流程(先 nameMap 再 KernelTable)RegisterAllKernelCommon():遍历 ELF kernels,按名称创建 Kernel 并注册到 kernelNameMap_
BinaryLoader 二进制加载器
功能描述:BinaryLoader 是内核注册的入口组件,负责从文件或内存加载二进制数据并创建对应的 Program 对象。它区分 CPU 算子和非 CPU 算子两种加载路径,支持多种加载选项。
核心方法功能:
| 方法 | 功能 |
|---|---|
Load() |
主入口,解析加载选项后分发到 LoadCpu 或 LoadNonCpu |
LoadNonCpu() |
非 CPU 路径:LoadProgram → UnifiedKernelRegister |
LoadCpu() |
CPU 路径:根据 isLoadFromFile 分发到 LoadCpuKernelFromFile 或 LoadCpuKernelFromData |
LoadFromFile()/LoadFromData() |
创建 ElfProgram,调用 Register + ParseKernelJsonFile |
ParseLoadOptions() |
解析加载选项(Magic、CPU Kernel Mode) |
CPU 注册三种模式:
- Mode 0:仅加载 JSON 文件(自研算子,只需要 JSON 描述)
- Mode 1:加载 SO + JSON 文件(自定义算子,需要 SO 和 JSON)
- Mode 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 + offset |
GetPrefetchCnt(kernel) |
计算 ICache 预取计数 |
其他子模块职责
- arg_loader/:参数从 Host 侧加载到 Device 侧的机制。UbArgLoader 使用 UB 缓存池,UmaArgLoader 支持 PCIE BAR 和多种分配策略,StarsArgManager 是流级参数管理基类(派生出 UbArgManage/PcieArgManage)
- args/:参数格式转换与分配。ArgsHandleAllocator 管理 RtArgsHandle 内存,ParaConvertor 实现 aclrt 新老参数格式适配
- elf.hpp / elf.cc:ELF 格式解析。ProcessObject 解析 ELF 文件提取内核符号,RtKernel/RtKernelMetaInfo 描述内核元信息,GetKernelTlvInfo 解析 TLV 格式属性
- kernel_utils.hpp / cc:内核任务参数计算工具。ComputeRatio 计算混合执行配额,ConvertTaskType/GetKernelTaskParams 提取任务参数
- program_common.hpp / cc:CPU 算子属性设置辅助。SetCpuKernelAttr 统一设置 CPU Kernel 的 SO/FuncName/OpType 属性
4.3 模块职责划分
| 模块 | 职责 | 位置 |
|---|---|---|
| Kernel | 内核元信息管理,支持 CPU/非 CPU 类型 | inc/kernel/kernel.hpp |
| KernelTable | stub→Kernel 有序映射表,二分查找 | inc/kernel/kernel.hpp |
| Program | 程序管理基类,二进制数据 + 内核查找 | inc/kernel/program.hpp |
| PlainProgram | CPU 算子程序管理 | inc/kernel/program.hpp |
| ElfProgram | ELF 内核程序管理 + 解析 | inc/kernel/program.hpp |
| BinaryLoader | 二进制加载入口,CPU/非 CPU 注册 | src/kernel/binary_loader.hpp |
| Module | 设备侧加载(仅旧 rtBinaryLoad 流程) | inc/kernel/module.hpp |
| Elf | ELF 格式解析 | inc/kernel/elf.hpp |
| KernelUtils | 内核任务参数计算 | src/kernel/kernel_utils.hpp |
| ProgramCommon | CPU 算子属性辅助 | src/kernel/program_common.hpp |
| ArgLoader | 参数 H2D 加载机制 | src/kernel/arg_loader/ |
| Args | 参数格式转换与分配 | src/kernel/args/ |
4.4 核心数据结构
classDiagram
class Program {
+binary_ void*
+binarySize_ uint64_t
+KernelTable_ rtKernelArray_t*
+kernelNameMap_ map~string,Kernel*~
+progId_ uint32_t
+progType_ uint32_t
+baseAddrAlign_ void*[]
+isNewBinaryLoadFlow_ bool
+Register(data, length) rtError_t
+GetKernelByName(name) const Kernel*
+AllKernelLookup(tilingKey) Kernel*
+Load2Device() rtError_t
}
class PlainProgram {
+RegisterCpuKernel(kernelInfos) rtError_t
+RegisterSingleCpuKernel(funcName, kernelName) rtError_t
+SymbolOffset(symbol, length) uint32_t
+LoadSize() uint32_t
}
class ElfProgram {
+elfData_ rtElfData*
+kernels_ RtKernel*
+ParserBinary() rtError_t
+UnifiedKernelRegister() rtError_t
+RegisterAllKernelCommon() rtError_t
+GetKernels() RtKernel*
}
class Kernel {
+program_ Program*
+name_ string
+tilingKey_ uint64_t
+kernelAttrType_ rtKernelAttrType
+kernelRegisterType_ KernelRegisterType
+offset1_ offset2_ uint32_t
+mixType_ uint8_t
+taskRation_ uint32_t
+cpuOpType_ string
+funcEntryType_ KernelFunctionEntryType
+GetFunctionDevAddr() rtError_t
+GetNameId() uint64_t
}
class KernelTable {
+kernelArr_ rtKernelArr_t*
+kernelMapLock_ SpinLock
+kernelInfoExtMap_ map
+programStubMultiMap_ multimap
+Add() rtError_t
+Lookup() Kernel*
+RemoveAll() rtError_t
}
class BinaryLoader {
+Load() rtError_t
+LoadNonCpu() rtError_t
+LoadCpu() rtError_t
+ParseLoadOptions() rtError_t
}
Program <|-- PlainProgram
Program <|-- ElfProgram
Program --> Kernel : kernelNameMap_/KernelTable_
Kernel --> Program : program_
KernelTable --> Kernel : kernelArr_
BinaryLoader --> Program : 创建
5. 关键文件索引
| 模块 | 文件路径 | 核心内容 |
|---|---|---|
| Kernel 核心类 | src/runtime/core/inc/kernel/kernel.hpp |
Kernel 类定义 + KernelTable 类定义 |
| Kernel 实现 | src/runtime/core/src/kernel/kernel.cc |
Kernel + KernelTable 实现 |
| Program | src/runtime/core/inc/kernel/program.hpp |
Program/PlainProgram/ElfProgram 定义 |
| Program 实现 | src/runtime/core/src/kernel/program.cc |
Program 三类实现 |
| Module | src/runtime/core/inc/kernel/module.hpp |
Module 类定义(仅旧 rtBinaryLoad 流程) |
| Module 实现 | src/runtime/core/src/kernel/module.cc |
Module::Load 等实现(仅旧 rtBinaryLoad 流程) |
| BinaryLoader | src/runtime/core/src/kernel/binary_loader.hpp |
BinaryLoader 类定义 |
| BinaryLoader 实现 | src/runtime/core/src/kernel/binary_loader.cc |
CPU/非 CPU 加载路径 |
| ELF 解析 | src/runtime/core/inc/kernel/elf.hpp |
ELF 数据结构定义 |
| ELF 实现 | src/runtime/core/src/kernel/elf.cc |
ProcessObject 等解析函数 |
| KernelUtils | src/runtime/core/src/kernel/kernel_utils.hpp |
工具函数声明 |
| KernelUtils 实现 | src/runtime/core/src/kernel/kernel_utils.cc |
工具函数实现 |
| ProgramCommon | src/runtime/core/src/kernel/program_common.hpp |
CPU 辅助函数声明 |
| ProgramCommon 实现 | src/runtime/core/src/kernel/program_common.cc |
SetCpuKernelAttr 实现 |
| ArgLoader | src/runtime/core/src/kernel/arg_loader/ |
参数加载机制 |
| Args | src/runtime/core/src/kernel/args/ |
参数转换与分配 |
| C 接口层 | src/runtime/api/api_c_kernel.cc |
rt 内核外部接口 |
| aclrt 实现 | src/acl/aclrt_impl/kernel.cpp |
aclrt 内核接口实现 |
本模块文档基于源码 src/runtime/core/src/kernel/ 分析。