【TVM教程】模块序列化指南

TVM 现已更新到 0.21.0 版本,TVM 中文文档已经和新版本对齐。

Apache TVM 是一个深度的深度学习编译框架,适用于 CPU、GPU 和各种机器学习加速芯片。更多 TVM 中文文档可访问 →https://tvm.hyper.ai/

在部署 TVM 运行时模块时,无论目标是 CPU 还是 GPU,TVM最终只需要一个动态共享库(dynamic shared library)。实现这一点的关键就在于统一的模块序列化机制。本文将介绍 TVM 模块序列化的格式标准与实现细节。

序列化(Serialization)

入口 API 为tvm.module.Moduleexport_library。在此函数内部,我们会执行以下步骤:

  1. 收集所有 DSO 模块(例如 LLVM 模块和 C 模块)。
  2. 在获得 DSO 模块后,调用save函数将它们保存到文件。
  3. 随后检查是否存在已导入的模块(imported modules),例如 CUDA、OpenCL 等。这里对模块类型不做限制。
    如果存在导入模块,我们将创建一个名为devc.o/dev.cc的文件(用于将这些导入模块的二进制数据打包进最终的动态库中),然后调用_PackImportsToLLVM_PackImportsToC来执行模块序列化。
  4. 最后,调用fcompile,其内部会调用_cc.create_shared,生成动态共享库。

备注

  1. 对于 C 源码模块(CSourceModule),我们会将它们编译并与 DSO 模块一同进行链接。
  2. 是否使用_PackImportsToLLVM_PackImportsToC取决于 TVM 是否启用了 LLVM。它们本质上实现的是相同的目标。

序列化底层机制与格式标准

序列化主要发生在_PackImportsToLLVM_PackImportsToC中。它们都会调用SerializeModule来序列化 runtime module。在SerializeModule函数中,我们首先会构造一个辅助类ModuleSerializer。它会以module为输入进行初始化,例如分配模块索引。随后可以调用其SerializeModule方法执行序列化。

为了更好地理解,让我们更深入地挖掘这个类的实现。

下面的代码用于构造ModuleSerializer

explicit ModuleSerializer(runtime::Module mod) : mod_(mod) { Init(); } private: void Init() { CreateModuleIndex(); CreateImportTree(); }

CreateModuleIndex()中,我们使用 DFS 遍历模块的导入关系并为每个模块分配索引。根模块固定为索引0

例如:

llvm_mod:imported_modules - cuda_mod

因此,LLVM 模块的索引将是 0,CUDA 模块的索引将是 1。

在构建完模块索引之后,我们将尝试构建导入树(CreateImportTree()),该导入树会在我们重新加载导出的库时用于恢复模块之间的导入关系。在我们的设计中,我们使用 CSR 格式来存储导入树,每一行对应父节点索引,而子数组中的索引对应其子模块索引。在代码中,我们使用import_tree_row_ptr_import_tree_child_indices_来表示它们。

在完成初始化之后,我们就可以使用SerializeModule函数来序列化模块。

在该函数的逻辑中,我们假设序列化格式如下所示:

binary_blob_size binary_blob_type_key binary_blob_logic binary_blob_type_key binary_blob_logic ... _import_tree _import_tree_logic

binary_blob_size是我们在本次序列化步骤中将会包含的 blob 数量。在我们的示例中会有三个 blob,分别对应 LLVM 模块、CUDA 模块以及_import_tree

binary_blob_type_key是模块的 blob 类型键。 对于 LLVM / C 模块,其 blob 类型键为_lib。对于 CUDA 模块,其类型键为cuda,可以通过module->type_key()获取。

binary_blob_logic是处理该 blob 的逻辑。 对于大多数 blob(例如 CUDA、OpenCL),我们会调用SaveToBinary函数将 blob 序列化为二进制。然而,对于 LLVM / C 模块,我们只会写入_lib,用于表示这是一个 DSO 模块。

备注
是否需要实现 SaveToBinary 虚函数取决于模块的使用方式。例如,如果模块中包含我们在重新加载动态共享库时需要的信息,那么我们就应该实现该函数。像 CUDA 模块,在重新加载动态共享库时我们需要将其二进制数据传递给 GPU 驱动,因此我们需要实现SaveToBinary来序列化其二进制数据。但对于主机侧模块(如 DSO 模块),在加载动态共享库时我们并不需要额外信息,因此不需要实现SaveToBinary。不过,如果未来我们希望记录一些关于 DSO 模块的元信息,我们也可以为 DSO 模块实现SaveToBinary

最后,除非我们的模块中仅有一个 DSO 模块并且它位于根位置,否则我们会写入一个键_import_tree。该键用于在重新加载导出的库时恢复模块导入关系,如前文所述。import_tree_logic的内容则是将import_tree_row_ptr_import_tree_child_indices_写入到流中。

在上述步骤完成后,我们会将最终结果打包进一个符号runtime::symbol::tvm_ffi_library_bin,该符号可在动态库中恢复。

现在,我们已经完成序列化部分。正如你所看到的,我们理论上可以支持导入任意模块。

反序列化

入口 API 是tvm.runtime.load。实际上,该函数会调用_LoadFromFile。 如果进一步展开,可以看到其对应的是Module::LoadFromFile

在我们的示例中,文件是deploy.so。根据其函数逻辑,我们会在dso_library.cc中调用module.loadfile_so,关键代码如下:

// Load the imported modules const char* library_bin = reinterpret_cast<const char*>( lib->GetSymbol(runtime::symbol::tvm_ffi_library_bin)); Module root_mod; if (library_bin != nullptr) { root_mod = ProcessLibraryBin(library_bin, lib); } else { // Only have one single DSO Module root_mod = Module(n); }``` 如前所述,我们会将 blob 打包进符号 `runtime::symbol::tvm_ffi_library_bin`· 中。 在反序列化阶段,我们会检查它。如果存在 `runtime::symbol::tvm_ffi_library_bin`,我们将调用 `ProcessLibraryBin`,其逻辑如下: ```c++ READ(blob_size) READ(blob_type_key) for (size_t i = 0; i < blob_size; i++) { if (blob_type_key == "_lib") { // construct dso module using lib } else if (blob_type_key == "_import_tree") { // READ(_import_tree_row_ptr) // READ(_import_tree_child_indices) } else { // call module.loadbinary_blob_type_key, such as module.loadbinary_cuda // to restore. } } // Using _import_tree_row_ptr and _import_tree_child_indices to // restore module import relationship. The first module is the // root module according to our invariance as said before. return root_module;

完成上述步骤后,我们会将ctx_address设置为root_module, 以便能够从根模块查找符号(使所有符号可见)。

最终,我们就完成了反序列化部分。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1188865.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实话不好听,但这才是考PMP®的真实现状...

在项目管理圈&#xff0c;PMP证书大家都不陌生&#xff0c;不少人都把它当成升职加薪、跳槽的“硬通货”。但说起考PMP&#xff0c;很多人只听过含金量高、好考的好话&#xff0c;却没留意到背后的变化。今天小赛就跟大家说实话&#xff1a;PMP考试虽然看着通过率高&#xff0c…

ActionQueue.dll文件丢失找不到问题 免费下载方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

2026年天津财产分割律所联系电话推荐:精准对接与使用建议 - 品牌推荐

在2026年的今天,随着社会经济结构的持续演变与个人财富形式的日益多元化,婚姻家庭关系中的财产分割问题变得愈发复杂与关键。天津作为一座兼具深厚历史底蕴与现代经济活力的直辖市,此类纠纷不仅涉及传统的房产、存款…

ActiveSyncCsp.dll文件丢失找不到问题 免费下载方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

2026年冷链监控方案/冷链解决方案/冷链管理方案/智慧冷链方案/冷链数字化方案,推荐苏州聚元微电子股份有限公司 - 品牌策略师

2026年冷链监控方案/冷链解决方案/冷链管理方案/智慧冷链方案/冷链数字化方案,推荐苏州聚元微电子股份有限公司在食品安全与医药供应链要求日益严苛的今天,高效、可靠的冷链物流方案已成为保障民生与产业升级的关键。…

AcXtrnal.dll文件丢失找不到问题 免费下载方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

【Triton 教程】triton_language.where

Triton 是一种用于并行编程的语言和编译器。它旨在提供一个基于 Python 的编程环境&#xff0c;以高效编写自定义 DNN 计算内核&#xff0c;并能够在现代 GPU 硬件上以最大吞吐量运行。 更多 Triton 中文文档可访问 →triton.hyper.ai/ triton.language.where(condition, x, …

从VS Code到TRAE:OpenCSG公益课讲清AI IDE选型

由特许全球金融科技师CGFT认证项目(Chartered Global FinTech) 、模速空间与OpenCSG(开放传神)联合推出《普通人的AI掘金课——6天学会,马上能用》系列直播课程,给了一个很实用的结论:AI 编程工具的差异,往往不…

宝塔apache环境配置nodejs管理后台解决接口跨域问题

Apache 的反向代理规则和 Nginx 不一样,得换 Apache 的配置方式。核心问题:Apache 的反向代理配置方式宝塔中 Apache 的反向代理需要通过「虚拟主机配置文件」添加ProxyPass规则,而不是 Nginx 的location配置。步骤…

AdaptiveCards.dll文件丢失找不到问题 免费下载方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

2026年宝妈必看!“活性营养+好消化”奶粉TOP11排行榜:皇家美素佳儿凭3大“硬实力”稳占C位 - 行业调研院

凌晨3点爬起来冲奶粉的妈妈都懂——选对奶粉,等于给宝宝买了“肠胃保险”+“免疫盾牌”。但面对货架上琳琅满目的奶粉,怕奶源掺假、怕营养虚标、怕宝宝喝了便秘/感冒,简直像在“开盲盒”。 结合2026年最新母婴行业数…

acproxy.dll文件丢失找不到问题 免费下载方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

2026年天津财产分割律所联系电话推荐:专业团队与核心优势 - 品牌推荐

在2026年的今天,随着社会经济结构的持续变化与个人财富形式的日益多样化,婚姻家事纠纷中的财产分割问题变得愈发复杂与关键。尤其是在天津这样一座融合了传统与现代的直辖市,从老城区的房产继承与分割,到新兴商业区…

财务年终总结怎么写?这份专业PPT的结构值得借鉴

临近年底&#xff0c;撰写一份既能展示专业成果又能体现未来规划的年终总结&#xff0c;对各部门负责人来说都是一项重要任务。财务部门的工作总结尤其需要做到严谨准确、价值清晰且不枯燥乏味。一份实用的《财务部年终总结》PPT模板为此提供了很好的参考。该模板不仅在内容上展…

智能AI开发工具全景:从编码助手到模型训练平台的技术实践与演进

人工智能开发已形成完整工具链生态&#xff0c;从底层代码生成到顶层模型部署&#xff0c;各类AI工具正重塑软件开发范式。本文系统剖析智能编码工具、数据标注平台、模型训练框架三类核心工具的技术原理&#xff0c;通过代码示例、流程图解和实践案例&#xff0c;展现AI开发工…

以定制化创发展,以个性化赢未来|天津荣联汇智在全瓦通峰会分享智能化转型新路径

2026年1月15日至16日&#xff0c;“全瓦通巡讲峰会陕西站”成功举办&#xff0c;峰会以“以定制化创发展&#xff0c;以个性化赢未来”为主题&#xff0c;汇聚行业专家与企业代表&#xff0c;共同探讨印刷包装行业2026年发展趋势及新时代破局之道。天津长荣集团子公司——天津荣…

网页大文件分片上传原理中如何实现秒传和续传的源码?

《一个.NET码农的奇幻漂流——20G文件上传历险记》 甲方需求说明书&#xff08;魔幻现实主义版&#xff09; “兄弟&#xff0c;我们要做个能在IE8上传20G文件的功能&#xff0c;要支持文件夹结构保留、断点续传、加密传输&#xff0c;预算是100块哈&#xff01;对了&#xf…

阿里云PolarDB发布全面内化的AI能力,重新定义“AI就绪数据库”

1月20日&#xff0c;在2026阿里云PolarDB开发者大会上&#xff0c;阿里云旗下云原生数据库PolarDB正式发布AI数据湖库&#xff08;Lakebase&#xff09;等系列全新产品能力&#xff0c;将大模型能力内化为数据库的“血液”&#xff0c;让数据系统不仅能存储、查询多模态数据&am…

AcSpecfc.dll文件丢失找不到问题 免费下载方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

ACPI!AMLIAsyncEvalObject函数里对象数据如何传递给ACPI!AsyncCallBack--重要

ACPI!AMLIAsyncEvalObject函数里对象数据如何传递给ACPI!AsyncCallBack--重要 1: kd> kc # 00 ACPI!ACPIGetWorkerForInteger 01 ACPI!AsyncCallBack 02 ACPI!RunContext 03 ACPI!DispatchCtxtQueue 04 ACPI!StartTimeSlicePassive 05 ACPI!ACPIWorker 06 nt!PspSystemThre…