
ATVOSS DefaultKernelSchedulekernel 层默认调度策略的完整实现与使用指南【免费下载链接】atvossATVOSSAscend C Templates for Vector Operator Subroutines是一套基于Ascend C开发的Vector算子库致力于为昇腾硬件上的Vector类融合算子提供极简、高效、高性能、高拓展的编程方式。项目地址: https://gitcode.com/cann/atvoss导读DefaultKernelSchedule是 ATVOSSAscend C Templates for Vector Operator Subroutines中 kernel 层默认的 schedule 调度策略。它以完全继承BaseKernelSchedule能力的方式依据DefaultKernelConfig中的切分参数在昇腾 AI Core 上完成「多核任务划分 → 各核 GM 数据定位 → 下发 block 层执行」的完整调度逻辑。阅读本文后你将掌握DefaultKernelSchedule的模板参数含义、tiling 配置字段的计算规则、kernel 层Run的执行链路并能直接在KernelBuilder中正确装配该调度策略编写可运行的 Vector 融合算子。一、功能定位kernel 层调度策略在 ATVOSS 分层架构中的角色ATVOSS 将算子实现划分为 device 层、kernel 层与 block 层。DefaultKernelSchedule属于 kernel 层的调度类Schedule其职责与分层协作关系如下kernel 层负责根据总元素数量计算 tiling 信息核数、每核基本块数、尾块元素数等再依据当前核的blockIdx确定本核需要处理的 GM 数据区间把数据交给 block 层计算block 层kernel 层调度的被包含对象BlockOp在单核内完成 UB 缓冲管理、基本块循环与表达式求值device 层通过 DeviceAdapter 完成 tiling 计算与 kernel 启动LaunchKernelWithDataTuple。DefaultKernelSchedule是BaseKernelSchedule的默认实现二者在 include/elewise/kernel/schedule.h 中定义。从源码结构看DefaultKernelSchedule是一个空继承类未覆写任何成员其全部调度能力tiling 计算、参数准备、GM 偏移计算均来自基类BaseKernelSchedule这保证了默认策略与用户自定义策略拥有完全一致的接口契约。二、类模板原型与参数说明DefaultKernelSchedule的完整声明如下位于 include/elewise/kernel/schedule.h#L214-L215template typename BlockOp, const auto Policy, typename ScheduleCfg class DefaultKernelSchedule : public BaseKernelScheduleBlockOp, Policy, ScheduleCfg {};参数名称参数类型输入/输出数据类型参数说明默认值BlockOp模板参数输入NAblock 层对象类型与 kernel 层是被包含关系NAPolicy模板参数输入NAkernel 层的用户静态策略类型NAScheduleCfg模板参数输入NAkernel 层调度配置类型NA三个模板参数的取值通常为BlockOp由Atvoss::Ele::BlockBuilderCompute, ArchTag生成的 block 层对象类型PolicyAtvoss::Ele::DefaultKernelPolicy类型含segmentPolicy成员目前仅支持UniformSegment均匀切分定义于 include/elewise/kernel/builder.h#L24-L33ScheduleCfgAtvoss::Ele::DefaultKernelConfig类型即 kernel 层 tiling 配置结构体。返回值说明返回值数据类型返回值说明DefaultKernelSchedule返回默认的 kernel 层 schedule 调度策略对象约束说明原文档标注为 NA。结合源码实现可补充一条隐式约束ScheduleCfg必须提供blockNum / unitNumPerCore / moreUnitCoreNum / tailNum / unitNum这些成员字段即满足DefaultKernelConfig的字段布局否则基类中的 tiling 计算与核内元素计数逻辑将无法编译通过。三、调度配置的数据基础DefaultKernelConfig 字段解析DefaultKernelSchedule的调度逻辑围绕 DefaultKernelConfig 展开该结构体定义于 include/elewise/kernel/builder.h#L16-L22struct DefaultKernelConfig { // Kernel layer tiling information uint32_t blockNum 1; // Number of cores started uint64_t unitNumPerCore 0; // Average number of unit processed per core uint64_t moreUnitCoreNum 0; // Number of cores that need to process an additional full unit uint64_t tailNum 0; // Number of tail elements to be processed by the last core uint64_t unitNum 1; // Number of elements per unit block };各字段含义与默认值如下成员名称成员类型成员说明默认值blockNumuint32_t启用的核的数量1unitNumPerCoreuint64_t平均每个核处理的基本块个数0moreUnitCoreNumuint64_t核均分后需要处理额外多出来的基本块的核的数量0tailNumuint64_t最后一个核要处理的尾块元素数量0unitNumuint64_t基本块的元素数量1其中unitNum在调度执行时会被覆写为ACTUAL_N_ASSIGN见下文它代表单个基本块实际分配的元素数是 tiling 计算的最小粒度。四、调度原理深度解析从源码看 tiling 计算与核内执行4.1 编译期常量推导BaseKernelSchedule在编译期根据 block 层的TileShape推导出一组调度常量include/elewise/kernel/schedule.h#L35-L49static constexpr uint64_t TILE_SHAPE_SIZE TileShape::size::value; static constexpr uint64_t BASIC_BLOCK BlockOp::ScheduleClz::BASIC_BLOCK; static constexpr uint64_t ALIGN_TILE_SHAPE_SIZE 2; static constexpr uint64_t ACTUAL_N_ASSIGN TILE_SHAPE_SIZE 1 ? 32 : TileShape::template get_typeTILE_SHAPE_SIZE - 1::value; static constexpr uint64_t BASIC_CORE_ELE_NUM (BASIC_BLOCK ACTUAL_N_ASSIGN - 1) / ACTUAL_N_ASSIGN * ACTUAL_N_ASSIGN;BASIC_BLOCKblock 层单个 Tile 的元素个数由 block 层 policy 推导ACTUAL_N_ASSIGN基本块实际分配元素数——一维 Tile 形状下取 32多维取最后一维的元素数BASIC_CORE_ELE_NUM单个核最少能处理的对齐后元素数即BASIC_BLOCK向上对齐到ACTUAL_N_ASSIGN的整数倍。4.2 MakeScheduleConfighost 侧 tiling 计算MakeScheduleConfig是 kernel 层 schedule 的 host 侧静态接口输入用户参数列表输出ScheduleCfg即DefaultKernelConfig配置include/elewise/kernel/schedule.h#L57-L93。计算流程提取形状并校验从 arguments 的第一个输入中读取shape_vector()累乘得到totalEleNum若形状为空或总元素数为 0打印[ERROR]: [Atvoss][Kernel] Shape info error并返回false小数据量直接单核处理若totalEleNum BASIC_CORE_ELE_NUM则blockNum 1、tailNum totalEleNum其余字段置 0直接返回true多核均分basicCoreUnitNum BASIC_CORE_ELE_NUM / ACTUAL_N_ASSIGN单核可处理的对齐基本块数totalUnitCnt totalEleNum / ACTUAL_N_ASSIGN总基本块数blockNum ceil(totalUnitCnt / basicCoreUnitNum)且不超过ArchTag::CORE_NUM由 common/arch.h 提供的架构核数上限unitNumPerCore totalUnitCnt / blockNum每核平均基本块数moreUnitCoreNum totalUnitCnt % blockNum多分到一个基本块的核数tailNum totalEleNum % ACTUAL_N_ASSIGN最后一个核负责的尾元素数。该接口在整个调用链中的位置可见于 device_adapter.h#L128-L140CalcParam依次调用KernelOp::ScheduleClz::MakeScheduleConfig生成 kernel 层配置再调用BlockOp::ScheduleClz::MakeScheduleConfig生成 block 层配置。4.3 Rundevice 侧核内调度执行Run是 kernel 层在 AI Core 上执行的入口include/elewise/kernel/schedule.h#L117-L130完成三件事计算本核元素总数CalCurCoreEleCnt依据AscendC::GetBlockIdx()判断当前核归属——若blockIdx moreUnitCoreNum则多分一个基本块若blockIdx blockNum - 1则追加tailNum尾元素准备参数PrepareParams根据编译期推导出的Params列表逐个构造参数其中 Tensor 参数通过CalGMOffset计算本核在 GM 中的起始偏移blockIdx * unitNumPerCore * unitNum moreUnitCoreNum * unitNum的均匀划分公式将 GM 地址指针按数据类型大小平移后传入标量参数则直接透传或解引用下发 block 层组装configBlock含totalElemCnt与参数元组构造BlockOp并调用blockOp.Run(...)由 BaseBlockSchedule::Run 继续按BASIC_BLOCK切分wholeLoop与tileCnt循环求值。值得注意Run定义在#if !defined(__ATVOSS_HOST_ONLY__)分支内即仅编译进 device 侧代码host 侧仅暴露MakeScheduleConfig静态接口用于 tiling 计算这正是 ATVOSS 将 host/device 代码通过宏隔离的典型模式。五、在 KernelBuilder 中装配 DefaultKernelScheduleDefaultKernelSchedule是 KernelBuilder 的第四个模板参数调度类型的默认值定义于 include/elewise/kernel/builder.h#L39-L48template typename BlockOp, const auto Policy defaultKernelPolicy, typename ScheduleCfg DefaultKernelConfig, template typename, const auto, typename class Schedule DefaultKernelSchedule class KernelBuilder { ... };因此常规写法Atvoss::Ele::KernelBuilderBlockOp, kernelPolicy内部即隐式使用DefaultKernelScheduleDefaultKernelConfig。当用户需要自定义调度时可在第四个模板参数处替换为自己的 Schedule 类同样须继承自BaseKernelSchedule。六、完整使用示例以下示例实现out in1 in2 - in3两个 Tensor 输入减一个标量输入完整演示如何将DefaultKernelSchedule显式装配进KernelBuildertemplate typename InputDtype, typename OutputDtype struct AddSubConfig { struct AddSubCompute { template template typename class Tensor __host_aicore__ constexpr auto Compute() const { auto in1 Atvoss::PlaceHolder1, TensorInputDtype, Atvoss::ParamUsage::IN(); auto in2 Atvoss::PlaceHolder2, TensorInputDtype, Atvoss::ParamUsage::IN(); auto in3 Atvoss::PlaceHolder3, InputDtype, Atvoss::ParamUsage::IN(); auto out Atvoss::PlaceHolder4, TensorOutputDtype, Atvoss::ParamUsage::OUT(); return (out in1 in2 - in3); }; }; static constexpr Atvoss::Ele::DefaultKernelPolicy kernelPolicy{Atvoss::Ele::DefaultSegmentPolicy::UniformSegment}; using ArchTag Atvoss::Arch::DAV_3510; using BlockOp Atvoss::Ele::BlockBuilderAddSubCompute, ArchTag; using KernelOp Atvoss::Ele::KernelBuilder BlockOp, kernelPolicy, Atvoss::Ele::DefaultKernelConfig, // 使用示例 Atvoss::Ele::DefaultKernelSchedule // 使用示例 ; using DeviceOp Atvoss::DeviceAdapterKernelOp; }; template typename InputDtype, typename OutputDtype static void Run() { /* ACL init and stream create */ ... Atvoss::TensorInputDtype in1(deviceIn1, {{3, 4, 0, 0, 0, 0, 0, 0}}, 2); Atvoss::TensorInputDtype in2(deviceIn2, {{3, 4, 0, 0, 0, 0, 0, 0}}, 2); InputDtype in3 5.0; Atvoss::TensorOutputDtype out(deviceOut, {{3, 4, 0, 0, 0, 0, 0, 0}}, 2); auto arguments Atvoss::ArgumentsBuilder{}.inputOutput(in1, in2, in3, out).attr(dim, 5).build(); using DeviceOp typename AddSubConfigInputDtype, OutputDtype::DeviceOp; DeviceOp deviceOp; deviceOp.Run(arguments, stream); } int main(int argc, char const* argv[]) { Runfloat, float(); return 0; }代码要点kernelPolicy采用DefaultSegmentPolicy::UniformSegment均匀切分当前唯一支持的切分方式BlockBuilder生成 block 层对象KernelBuilder以BlockOp kernelPolicy DefaultKernelConfig DefaultKernelSchedule组装 kernel 层DeviceAdapter负责在 host 侧驱动MakeScheduleConfig生成 tiling再以opParam.kernelParam.blockNum作为启动核数调用LaunchKernelWithDataTuple拉起 kernel运行期每个核通过AscendC::GetBlockIdx()在Run内确定自己的数据区间实现多核并行。该模式与仓库内 examples/muls/muls.cpp 等官方示例的编写方式一致可作为实际算子开发的参照。七、约束、局限与总结切分策略约束DefaultKernelPolicy目前仅支持UniformSegment均匀切分若需按非均匀方式如按 shape 维度特化切分划分数据需要自定义继承自BaseKernelSchedule的调度类核数上限blockNum被ArchTag::CORE_NUM截断超大 shape 下不会超过目标架构可用核数调度粒度kernel 层以「基本块unit」为最小调度单元block 层再按BASIC_BLOCK细分循环两级切分共同决定了数据在核间与核内的分布接口契约无论默认还是自定义调度都必须实现 host 侧MakeScheduleConfig与 device 侧Run两个接口且ScheduleCfg需与KernelBuilder传入的配置类型一致。DefaultKernelSchedule以极小的代码量单行继承声明复用了BaseKernelSchedule完整的多核 tiling 与数据分发逻辑是 ATVOSS「极简编程」理念在调度层的集中体现。理解它的 tiling 计算规则与核内执行链路是进一步自定义 kernel 层调度、编写高性能 Vector 融合算子的基础。相关文档导航BaseKernelSchedule::MakeScheduleConfigtiling 配置生成接口详解BaseKernelSchedule::Run核内调度执行接口详解DefaultKernelConfig调度配置结构体DefaultKernelPolicykernel 层静态策略KernelBuilderkernel 层对象构建类DefaultBlockScheduleblock 层默认调度策略DeviceAdapterdevice 层适配与 kernel 启动【免费下载链接】atvossATVOSSAscend C Templates for Vector Operator Subroutines是一套基于Ascend C开发的Vector算子库致力于为昇腾硬件上的Vector类融合算子提供极简、高效、高性能、高拓展的编程方式。项目地址: https://gitcode.com/cann/atvoss创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考