news 2026/10/16 3:19:01

asc-devkit 算子调测实战:用 SetOpNameType 为 ContextBuilder 构造 Tiling 上下文指定算子名字与类型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
asc-devkit 算子调测实战:用 SetOpNameType 为 ContextBuilder 构造 Tiling 上下文指定算子名字与类型
  • 人工智能
  • 深度学习
  • 算子库
  • CANN
  • Ascend

【免费下载链接】asc-devkit

本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。

项目地址:https://gitcode.com/cann/asc-devkit
点击查看免费下载

本文围绕 asc-devkit 算子调测(Tiling 调测)工具链中的context_ascendc::ContextBuilder::SetOpNameType接口展开,说明其函数原型、参数含义与返回值语义,并结合开源仓库源码剖析其底层调用链、默认值行为,以及与OpTilingRegistry按算子类型查找 Tiling 函数之间的关系。读完后,你可以独立编写可运行的 Tiling 调测代码,为手动构造的TilingContext正确设置算子身份,并将opType与注册表机制正确对应。

一、功能定位:Tiling 调测中的算子身份设置

在算子开发流程中,Tiling 函数(计算分块参数的 Host 端函数)通常运行在运行时上下文中,难以脱离推理框架单独调试。asc-devkit 为此提供了 Tiling 调测能力:ContextBuilder类提供一系列 Builder 风格 API,支持手动构造TilingContext来验证 Tiling 函数,以及手动构造KernelContext来验证TilingParse函数(见 Tiling 调测 ContextBuilder 简介)。

在手动构造TilingContext时,必须让上下文携带正确的"算子身份",即算子名字(opName)与算子类型(opType)。SetOpNameType正是承担这一职责的接口:

  • 属于OpInfo(算子信息)分组,与NodeIoNum、IrInstanceNum、AddInputTd、AddOutputTd、AddAttr等接口共同描述"这是一个什么算子、有多少输入输出、有哪些属性";
  • 是TilingContext构建链路的起始信息之一,通常与NodeIoNum、IrInstanceNum搭配使用;
  • 返回ContextBuilder自身的引用,支持链式调用。

接口声明位于 ContextBuilder 公开头文件:

ContextBuilder &SetOpNameType(const std::string& opName, const std::string& opType);

二、函数原型与参数说明

函数原型:

ContextBuilder &SetOpNameType(const std::string& opName, const std::string& opType)

参数说明:

参数输入/输出说明
opName输入算子名字。通常对应图中节点的实例名,例如自定义算子在图中的节点名,用于日志定位与调试标识
opType输入算子类型。对应注册到算子实现空间(OpImplSpace)中的算子类型名,是 Tiling 函数注册与查找的关键键值

返回值说明:当前ContextBuilder的对象(即以引用形式返回调用者自身,支持链式调用)。

约束说明:文档未定义额外约束。从源码看,内部仅通过ASCENDC_ASSERT检查实现指针impl_非空,异常时会输出impl_ is nullptr!错误日志并提前返回。

三、源码剖析:SetOpNameType 的调用链与默认值行为

3.1 公开接口层:断言 + 委托 + 链式返回

SetOpNameType在 ContextBuilder 实现文件 中的实现非常简洁:

ContextBuilder& ContextBuilder::SetOpNameType(const std::string& opName, const std::string& opType) { ASCENDC_ASSERT(impl_ != nullptr, return *this, CXT_ASCENDC_LOGE("impl_ is nullptr!")); impl_->SetOpNameType(opName, opType); return *this; }

这体现了ContextBuilder整体采用的 pimpl(指针到实现)+ 链式调用设计:公开类内部持有std::unique_ptr<ContextBuilderImpl> impl_(见 context_builder.h),每个 Setter 都先做非空断言,再委托给ContextBuilderImpl,最后return *this保证整条链式调用不断开。

3.2 实现层:写入 tilingCtxBuilder_ 的 OpName/OpType

ContextBuilderImpl 的实现 中,SetOpNameType被拆解为两个底层动作,写入gert::OpTilingContextBuilder:

void ContextBuilderImpl::SetOpNameType(const std::string& opName, const std::string& opType) { ASCENDC_ASSERT(tilingCtxBuilder_ != nullptr, return, CXT_ASCENDC_LOGE("tilingCtxBuilder_ is nullptr!")); tilingCtxBuilder_->OpName(opName.c_str()); tilingCtxBuilder_->OpType(opType.c_str()); }

ContextBuilderImpl内部维护两个底层 Builder(见 context_builder_impl.h):

  • gert::OpKernelContextBuilder kernelCtxBuilder_:面向KernelContext(验证 TilingParse 函数);
  • gert::OpTilingContextBuilder tilingCtxBuilder_:面向TilingContext(验证 Tiling 函数)。

因此可以确认:SetOpNameType只影响 TilingContext 构建链路。这与接口分组一致——它声明在头文件的 "OpInfo" 区域,而BuildTilingContext()才消费tilingCtxBuilder_累积的信息。

3.3 默认值行为:不调用 SetOpNameType 时会发生什么

从源码结构看,ContextBuilderImpl 构造函数 中已经为两个底层 Builder 预设了占位身份:

ContextBuilderImpl::ContextBuilderImpl() { kernelCtxBuilder_ = std::make_unique<gert::OpKernelContextBuilder>(); tilingCtxBuilder_ = std::make_unique<gert::OpTilingContextBuilder>(); tilingCtxBuilder_->OpName("default_name").OpType("default_type").IONum(1, 1); tilingCtxBuilder_->CompileInfo("default_compileinfo").PlatformInfo("default_platforminfo"); kernelCtxBuilder_->OpName("default_name").OpType("default_type").IONum(1, 1); }

也就是说,即使不调用SetOpNameType,构造出的TilingContext也会携带opName = "default_name"、opType = "default_type"的占位身份。这意味着:

  • 在纯调测场景(Tiling 函数不依赖算子身份做逻辑分支)下,SetOpNameType可以省略;
  • 但如果你要复现真实算子行为(Tiling 函数或后续流程可能读取 opType 做实现选择),应显式传入真实的算子类型名,避免使用default_type占位。

四、opType 的深层作用:与 OpTilingRegistry 的注册表查找机制联动

opType之所以是关键参数,是因为 Tiling 调测体系中还有一个配套类OpTilingRegistry,它负责按算子类型查找已注册的 Tiling 函数。查看 OpTilingRegistry::GetTilingFunc 的实现:

TilingFunc OpTilingRegistry::GetTilingFunc(const char* opType) const { auto registry = gert::DefaultOpImplSpaceRegistryV2::GetInstance().GetSpaceRegistry(); const gert::OpImplKernelRegistry::OpImplFunctionsV2* funcs; if (registry == nullptr) { CXT_ASCENDC_LOGD("failed to find implfuncs in 2.0 way, registery is null. op type is %s.", opType); return nullptr; } funcs = registry->GetOpImpl(opType); if (funcs == nullptr || funcs->tiling == nullptr || funcs->tiling_parse == nullptr) { return nullptr; } CXT_ASCENDC_LOGD("find implfuncs in 2.0 way, op type is %s.", opType); return funcs->tiling; }

从源码结构看,GetTilingFunc(opType)以opType 字符串作为键,在DefaultOpImplSpaceRegistryV2注册表中查找对应的tiling函数指针(前提是tiling与tiling_parse均已注册)。这提示了SetOpNameType使用时的一个重要实践点:

  • 传入的opType应与算子在注册表/框架中登记算子类型保持一致,否则后续按 opType 取 Tiling 函数会得到nullptr,调试流程走不通;
  • OpTilingRegistry还支持LoadTilingLibrary(tilingSoPath)动态加载算子 Tiling 库(内部通过dlopen+ 调用TbeLoadSoAndSaveToRegistry完成注册,见 实现代码),加载后同样以 opType 为键查询。

文档原文给出的调用示例中opType = "FlashAttentionScore"正是这种"真实算子类型名"的用法。

五、调用示例

5.1 文档标准示例(最小用法)

std::string opName = "tmpNode"; std::string opType = "FlashAttentionScore"; context_ascendc::ContextBuilder builder; (void)builder.SetOpNameType(opName, opType);

说明:

  • opName = "tmpNode":模拟图中一个节点名(算子实例名);
  • opType = "FlashAttentionScore":一个真实的算子类型名;
  • 返回值用(void)显式丢弃,表达"我只要设置状态,不关心链式返回"的意图;由于接口返回自身引用,丢弃返回值不影响后续通过builder继续链式调用。

5.2 完整调测链路:SetOpNameType 在 TilingContext 构建中的位置

结合 ContextBuilder 简介文档 给出的标准用法,SetOpNameType是手动构造TilingContext链条中的基础一环:

// 构造TilingContext auto tilingContextHolder = context_ascendc::ContextBuilder() .SetOpNameType("MyOp", "MyOpType") // 指定算子名字与类型 .NodeIoNum(2, 1) // 2 个输入、1 个输出 .IrInstanceNum({1, 1}) // 各输入的 IR 实例数 .AddInputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND, input_shape) .AddInputTd(1, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND, weight_shape) .AddOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND, output_shape) .AddAttr("activation", std::string("gelu")) .TilingData(param.get()) .Workspace(ws_size) .BuildTilingContext(); gert::TilingContext* tilingContext = tilingContextHolder->GetContext<gert::TilingContext>();

ContextBuilder头文件中完整的 TilingContext 构建 API 面(SetOpNameType、NodeIoNum、IrInstanceNum、AddInputTd、AddOutputTd、AddAttr、CompileInfo、PlatformInfo、TilingData、Workspace、BuildTilingContext)均可在 context_builder.h 查阅。

5.3 仓库单元测试中的真实用法

仓库单测 test_tiling.cpp 大量使用了该接口,例如:

auto holder = context_ascendc::ContextBuilder() .NodeIoNum(1, 1) .IrInstanceNum({1}) .SetOpNameType("tmpName", "tmpType") .AddInputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND, input_shape, file_path) .AddOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND, output_shape) .TilingData(param.get()) .Workspace(ws_size) .BuildTilingContext();

测试同时覆盖了多输入多属性场景(6 输入 1 输出、混合常量值/二进制文件输入、多种类型的AddAttr),验证了SetOpNameType与其余 OpInfo 接口在长链式调用中的稳定组合方式(见 TestTilingContextBuildWithBinFile 等用例)。需要说明的是,这些用例的调测目标是BuildTilingContext的容错行为(如常量数据文件缺失时返回空 holder),其中传入的"tmpName"/"tmpType"仅为占位身份。

六、使用要点与注意事项

  1. 返回自身引用,链式调用不断开:SetOpNameType返回ContextBuilder&,可与NodeIoNum、AddInputTd等任意 Setter 自由组合;若单独调用,可像文档示例那样用(void)丢弃返回值。
  2. opName 与 opType 语义不同:opName 是节点实例名,偏标识与日志用途;opType 是算子类型,是注册表查找 Tiling 函数的键。构造真实调测环境时应优先保证 opType 与算子注册类型一致。
  3. 默认占位值兜底:不调用该接口时,上下文会携带default_name/default_type占位身份(由ContextBuilderImpl构造函数预设),不会导致空值崩溃,但依赖 opType 的逻辑将无法正确路由。
  4. 仅作用于 TilingContext 链路:从源码看,SetOpNameType写入的是tilingCtxBuilder_,由BuildTilingContext()消费;BuildKernelRunContext()走的是kernelCtxBuilder_(其 OpName/OpType 在构造时以默认值初始化),两条链路相互独立。
  5. 无额外前置约束:接口文档约束说明为"无",源码层仅有内部指针非空断言,属于可安全重复调用的 Setter,后一次调用会覆盖前一次设置的算子身份。

七、相关文档与源码索引

类型路径
本文对应 API 文档SetOpNameType.md
ContextBuilder 调测简介intro.md
ContextBuilder 公开头文件context_builder.h
ContextBuilder 实现(含 OpTilingRegistry 查找逻辑)context_builder.cpp
ContextBuilderImpl 声明context_builder_impl.h
ContextBuilderImpl 实现context_builder_impl.cpp
Tiling 调测单元测试test_tiling.cpp
  • 人工智能
  • 深度学习
  • 算子库
  • CANN
  • Ascend

【免费下载链接】asc-devkit

本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。

项目地址:https://gitcode.com/cann/asc-devkit
点击查看免费下载

相关推荐

上一篇:终极指南:FlatBuffers vs Protobuf - C++服务器协议编解码性能深度对比
下一篇:Makepad响应式布局设计:自适应屏幕尺寸的UI解决方案

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/16 3:17:36

用Python和Redis手写一个轻量任务队列,附完整代码

简介&#xff1a;这是一份基于 Python 与 Redis 的轻量级任务队列示例资源&#xff0c;主要面向需要快速实现异步任务处理的 Python 开发者。项目利用 RQ&#xff08;Redis Queue&#xff09;库&#xff0c;展示了如何将耗时任务放入队列并由独立 Worker 消费执行&#xff0c;适…

作者头像 李华
网站建设 2026/10/16 3:17:13

还在寻找 Xshell 的替代:2026 年值得关注的现代 SSH 客户端

要是你还在用 Xshell 搭配 XFTP 管理服务器&#xff0c;估计也有感觉&#xff1a;这套组合虽然经典&#xff0c;但跨平台、SFTP 集成、AI 辅助这些方面确实有点跟不上了。我最近折腾了一圈新一代 SSH 工具&#xff0c;发现选择比想象中多。 为什么现在要重新考虑远程管理工具 X…

作者头像 李华
网站建设 2026/10/16 3:17:12

亚马逊账号安全如何保障?五大核心注意要点

亚马逊防关联作为重品牌、重合规、审核最严&#xff0c;单店做大容易&#xff0c;多店扩张的合规门槛最高。亚马逊店铺做多之后&#xff0c;账号关联判定维度最多&#xff0c;历史订单、收款、网络环境、设备指纹都会被交叉比对 这篇围绕亚马逊防关联展开&#xff0c;先把防关…

作者头像 李华
网站建设 2026/10/16 3:17:11

从零构建Agent:大模型调用、工具设计与多步规划的进阶路线

经常有朋友问我&#xff1a;“从零构建 Agent&#xff0c;到底该按什么顺序学&#xff1f;”说实话&#xff0c;这个问题比想象中难回答。因为市面上讲 Agent 的教程很多&#xff0c;但大多数是教你“怎么调用某框架的某个接口”&#xff0c;而不是教你“为什么这个能力要放在那…

作者头像 李华
网站建设 2026/10/16 3:17:00

感知普遍性与本源不可感知| 赵杰 | 量子感知论

作者&#xff1a;赵杰清华大学硕士、微美全息云科技&#xff08;NASDAQ&#xff1a;WIMI&#xff09;董事长、微算法科技&#xff08;NASDAQ&#xff1a;MLGO&#xff09;董事长、育杰奖学金创始人人类所能感知的一切现象——时间、空间、物质、能量、粒子、星体、宇宙、数理规…

作者头像 李华