【TVM 学习资料】TensorIR 快速入门

TVM Relax抽象层:动态深度学习模型编译与部署新范式 深度学习编译器是连接算法模型与硬件执行的关键桥梁,其核心在于将高级框架描述的计算图转换为高效的底层代码。传统静态编译方案在处理动态形状、可变输入和控制流时面临挑战,这推动了支持动态性的中间表示设计。TVM Relax抽象层通过引入符号形状、动态类型系统和交互式编译流程,为动态模型提供了原生支持,显著提升了编译灵活性和开发体验。该技术特别适用于自然语言处理中可变序列长度、动态路由网络等场景,通过call_tir机制将高层图优化与底层性能调优解耦,实现了从动态图描述到高性能硬件代码的端到端编译。Relax与Re 阅读详情

本篇文章译自英文文档 Blitz Course to TensorIR
作者是 Siyuan Feng。更多 TVM 中文文档可访问→TVM 中文站

TensorIR 是深度学习领域的特定语言,主要有两个作用:

  • 在各种硬件后端转换和优化程序。
  • 自动 tensorized 程序优化的抽象。
import tvm
from tvm.ir.module import IRModule
from tvm.script import tir as T
import numpy as np

IRModule

IRModule 是 TVM 的核心数据结构,它包含深度学习程序,并且是 IR 转换和模型构建的基础。

在这里插入图片描述
上图展示的是 IRModule 的生命周期,它可由 TVMScript 创建。转换 IRModule 的两种主要方法是 TensorIR 的 schedule 原语转换和 pass 转换。此外,也可直接对 IRModule 进行一系列转换。注意,可以在任何阶段将 IRModule 打印到 TVMScript。完成所有转换和优化后,可将 IRModule 构建为可运行模块,从而部署在目标设备上。

基于 TensorIR 和 IRModule 的设计,可创建一种新的编程方法:

  1. 基于 Python-AST 语法,用 TVMScript 编写程序。
  2. 使用 Python API 转换和优化程序。
  3. 使用命令式转换 API 交互检查和提高性能。

创建 IRModule

IRModule 是 TVM IR 的一种可往返语法,可通过编写 TVMScript 来创建。

与通过张量表达式创建计算表达式(使用张量表达式操作算子)不同,TensorIR 允许用户通过 TVMScript(一种嵌在 Python AST 中的语言)进行编程。新方法可以编写复杂的程序并进一步调度和优化。

下面是向量加法的示例:

@tvm.script.ir_module
class MyModule:
    @T.prim_func
    def main(a: T.handle, b: T.handle):
        # 我们通过 T.handle 进行数据交换,类似于内存指针
        T.func_attr({"global_symbol": "main", "tir.noalias": True})
        # 通过 handle 创建 Buffer
        A = T.match_buffer(a, (8,), dtype="float32")
        B = T.match_buffer(b, (8,), dtype="float32")
        for i in range(8):
            # block 是针对计算的抽象
            with T.block("B"):
                # 定义一个空间(可并行)block 迭代器,并且将它的值绑定成 i
                vi = T.axis.spatial(8, i)
                B[vi] = A[vi] + 1.0

ir_module = MyModule
print(type(ir_module))
print(ir_module.script())

输出结果:

<class 'tvm.ir.module.IRModule'>
# from tvm.script import tir as T
@tvm.script.ir_module
class Module:
    @T.prim_func
    def main(A: T.Buffer[8, "float32"], B: T.Buffer[8, "float32"]) -> None:
        # function attr dict
        T.func_attr({"global_symbol": "main", "tir.noalias": True})
        # body
        # with T.block("root")
        for i in T.serial(8):
            with T.block("B"):
                vi = T.axis.spatial(8, i)
                T.reads(A[vi])
                T.writes(B[vi])
                B[vi] = A[vi] + T.float32(1)

此外,我们还可以使用张量表达式 DSL 编写简单的运算符,并将它们转换为 IRModule。

from tvm import te

A = te.placeholder((8,), dtype="float32", name="A")
B = te.compute((8,), lambda *i: A(*i) + 1.0, name="B")
func = te.create_prim_func([A, B])
ir_module_from_te = IRModule({"main": func})
print(ir_module_from_te.script())

输出结果:

# from tvm.script import tir as T
@tvm.script.ir_module
class Module:
    @T.prim_func
    def main(A: T.Buffer[8, "float32"], B: T.Buffer[8, "float32"]) -> None:
        # function attr dict
        T.func_attr({"global_symbol": "main", "tir.noalias": True})
        # body
        # with T.block("root")
        for i0 in T.serial(8):
            with T.block("B"):
                i0_1 = T.axis.spatial(8, i0)
                T.reads(A[i0_1])
                T.writes(B[i0_1])
                B[i0_1] = A[i0_1] + T.float32(1)

构建并运行 IRModule

可将 IRModule 构建为特定 target 后端的可运行模块。

mod = tvm.build(ir_module, target="llvm")  # CPU 后端的模块
print(type(mod))

输出结果:

<class 'tvm.driver.build_module.OperatorModule'>

准备输入数组和输出数组,然后运行模块:

a = tvm.nd.array(np.arange(8).astype("float32"))
b = tvm.nd.array(np.zeros((8,)).astype("float32"))
mod(a, b)
print(a)
print(b)

输出结果:

[0. 1. 2. 3. 4. 5. 6. 7.]
[1. 2. 3. 4. 5. 6. 7. 8.]

转换 IRModule

IRModule 是程序优化的核心数据结构,可通过 Schedule 进行转换。schedule 包含多个 primitive 方法来交互地转换程序。每个 primitive 都以特定方式对程序进行转换,从而优化性能。

在这里插入图片描述
上图是优化张量程序的典型工作流程。首先,用 TVMScript 或张量表达式创建一个初始 IRModule,然后在这个初始 IRModule 上创建 schedule。接下来,使用一系列调度原语来提高性能。最后,我们可以将其降低并构建成一个可运行模块。

上面只演示了一个简单的转换。首先,在输入 ir_module 上创建 schedule:

sch = tvm.tir.Schedule(ir_module)
print(type(sch))

输出结果:

<class 'tvm.tir.schedule.schedule.Schedule'>

将嵌套循环展开成 3 个循环,并打印结果:

# 通过名字获取 block
block_b = sch.get_block("B")
# 获取包围 block 的循环
(i,) = sch.get_loops(block_b)
# 展开嵌套循环
i_0, i_1, i_2 = sch.split(i, factors=[2, 2, 2])
print(sch.mod.script())

输出结果:

# from tvm.script import tir as T
@tvm.script.ir_module
class Module:
    @T.prim_func
    def main(A: T.Buffer[8, "float32"], B: T.Buffer[8, "float32"]) -> None:
        # function attr dict
        T.func_attr({"global_symbol": "main", "tir.noalias": True})
        # body
        # with T.block("root")
        for i_0, i_1, i_2 in T.grid(2, 2, 2):
            with T.block("B"):
                vi = T.axis.spatial(8, i_0 * 4 + i_1 * 2 + i_2)
                T.reads(A[vi])
                T.writes(B[vi])
                B[vi] = A[vi] + T.float32(1)

还可对循环重新排序。例如,将循环 i_2 移到 i_1 之外:

sch.reorder(i_0, i_2, i_1)
print(sch.mod.script())

输出结果

# from tvm.script import tir as T
@tvm.script.ir_module
class Module:
    @T.prim_func
    def main(A: T.Buffer[8, "float32"], B: T.Buffer[8, "float32"]) -> None:
        # function attr dict
        T.func_attr({"global_symbol": "main", "tir.noalias": True})
        # body
        # with T.block("root")
        for i_0, i_2, i_1 in T.grid(2, 2, 2):
            with T.block("B"):
                vi = T.axis.spatial(8, i_0 * 4 + i_1 * 2 + i_2)
                T.reads(A[vi])
                T.writes(B[vi])
                B[vi] = A[vi] + T.float32(1)

转换为 GPU 程序

要在 GPU 上部署模型必须进行线程绑定。幸运的是,也可以用原语来增量转换。

sch.bind(i_0, "blockIdx.x")
sch.bind(i_2, "threadIdx.x")
print(sch.mod.script())

输出结果:

# from tvm.script import tir as T
@tvm.script.ir_module
class Module:
    @T.prim_func
    def main(A: T.Buffer[8, "float32"], B: T.Buffer[8, "float32"]) -> None:
        # function attr dict
        T.func_attr({"global_symbol": "main", "tir.noalias": True})
        # body
        # with T.block("root")
        for i_0 in T.thread_binding(2, thread="blockIdx.x"):
            for i_2 in T.thread_binding(2, thread="threadIdx.x"):
                for i_1 in T.serial(2):
                    with T.block("B"):
                        vi = T.axis.spatial(8, i_0 * 4 + i_1 * 2 + i_2)
                        T.reads(A[vi])
                        T.writes(B[vi])
                        B[vi] = A[vi] + T.float32(1)

绑定线程后,用 cuda 后端来构建 IRModule:

ctx = tvm.cuda(0)
cuda_mod = tvm.build(sch.mod, target="cuda")
cuda_a = tvm.nd.array(np.arange(8).astype("float32"), ctx)
cuda_b = tvm.nd.array(np.zeros((8,)).astype("float32"), ctx)
cuda_mod(cuda_a, cuda_b)
print(cuda_a)
print(cuda_b)

输出结果:

[0. 1. 2. 3. 4. 5. 6. 7.]
[1. 2. 3. 4. 5. 6. 7. 8.]

下载 Python 源代码
下载 Jupyter Notebook

以上就是该文档的全部内容,查看更多 TVM 中文文档,请访问→TVM 中文站

mlc-llm:大语言模型跨平台高效部署的机器学习编译框架 机器学习编译(MLC)是一种将深度学习模型从高级框架表示转换为针对特定硬件优化的低级代码的技术。其核心原理在于通过中间表示(IR)实现硬件无关的抽象,再通过图级优化(如算子融合)和张量级优化(如循环变换)来最大化目标硬件的计算效率。这项技术的价值在于解决了模型部署中的硬件生态碎片化问题,使得单一模型能够在多种设备上高效运行,显著降低了多平台部署的复杂性和成本。其应用场景广泛,从云端服务器到边缘设备、移动终端乃至Web浏览器,都能通过编译优化获得接近原生的推理性能。本文聚焦的mlc-llm项目,正是这一技术在 阅读详情

相关推荐

用Matlab和CVX搞定原子范数最小化:一个信号处理小白的避坑实践

本文详细介绍了如何使用Matlab和CVX实现原子范数最小化(Atomic norm minimization),特别适合信号处理初学者。从CVX安装配置、核心代码解析到实战中的典型问题与解决方案,提供了全面的避坑指南。通过具体案例展示了原子范数在频率估计和DOA估计中的优势,并给出性能优化策略和可视化方法。

weixin_28731231的博客 232

TensorIR快速入门

本文翻译自Blitz Course to TensorIR — tvm 0.9.dev0 documentation TensorIR是一种用于深度学习程序的特定领域的语言,服务于两个广泛的目的: 在各种硬件后端上转换和优化程序的实现。 对自动向量化程序优化的抽象。 import tvm from tvm.ir.module import IRModule from tvm.script import tir as T import numpy as np IRModule IRModule是

zx_ros的博客 858

双轴按键摇杆模块原理与嵌入式驱动实战

双轴按键摇杆是一种融合模拟量(X/Y轴)与数字量(Z轴按键)的复合型人机交互传感器,其本质基于电位器分压原理与机械开关通断特性。通过ADC采集连续电压信号并结合数字IO检测按键状态,可实现高鲁棒性的二维运动感知与触发控制。该方案技术门槛低、成本可控、兼容性强,广泛应用于智能小车、DIY游戏手柄、工业HMI及教育开发板等嵌入式场景。文中深入解析电位器线性度、KEY引脚开漏特性、ADC参考电压稳定性及软件消抖状态机等关键工程要素,为基于Arduino、STM32或ESP32平台的快速集成提供可复用的技术路径。

weixin_30995917的博客 82

【MLC】 TensorIR 练习

这两天重新看了一下天奇的mlc课程文档,把里边儿的TensorIR 练习写了一下,顺便推广一下相关资料MLC-机器学习编译-B站MLC-文档bbuf老哥-B站Archer哥的二三事。

椰子奶糖的博客 924

别再花钱买商业软件了!这4款免费DIC工具,从散斑生成到应变分析全搞定

本文介绍了4款免费开源的DIC(数字图像相关技术)工具,涵盖从散斑生成到应变分析的全流程,帮助用户零成本构建专业级DIC工作流。这些工具在精度、算法透明度和生态整合方面具有优势,适用于材料力学和实验力学研究,可替代昂贵的商业软件。

weixin_42525369的博客 168

DeepSeek研发的精算大模型「精卫」已实现98%精算任务覆盖,中国人寿采用后年节约3.2亿元技术采购成本,形成关键技术替代效应

根据现有资料,精算领域关键技术替代效应的行业标准定义尚未明确具体提及。然而,可以从相关文献中提取一些关键概念和方法来推导出可能的定义。​替代效应的基本定义​:替代效应是指一种商品价格变动引起另一种商品的相对价格变动,从而导致消费者在维持原有效用水平不变的条件下对商品需求量做出的调整。​技术替代效应​:在精算领域,技术替代效应可以理解为新技术或新方法对现有技术或方法的替代,从而影响精算模型、数据处理和决策过程。例如,机器学习在精算中的应用日益增长,改变了精算师的工作方式和模型构建方法。​。

百态·数智思维 | 聚焦大数据、量化与未来AI 1712

机器学习编译(三):张量程序案例 TensorIR

当我们读取内存中的一个元素时,它会尝试将附近的元素(更正式的名称为“缓存行”)获取到缓存中。除了 TensorIR,TVM 中还可以用张量表示(Tensor Expression, TE)来做张量的抽象,这里略过,在介绍 TVM 的文章中再详细介绍。前面我们说了 TensorIR 是 TVM 里最接近硬件的 IR,而 IRModule 是 TVM 中可以编译的最小单位。是 TensorIR 中的基本计算单位。使用张量程序抽象,我们可以在较高层的抽象制定一些与特定硬件无关的较通用的 IR 优化(计算优化)。

RJ_theMag的博客 602

vue3 - element-plus表格组件el-table实现鼠标拖曳排序功能,vue3 Table表格拖拽排序,表格每行使用鼠标拖动进行排序功能,表格拖拽排序实现(详细示例代码,一键复制开箱即用

vue3,elementPlus,el-table,typescript,表格组件,Table表格,表格拖动排序,表格拖曳排序,鼠标拖拽表格进行排序功能,elementplus表格如何实现拖动每行进行排序操作,表格拖动改变顺序,鼠标拖曳,表格内的数据项拖拽排序,vue3如何实现element-Plus表格组件进行表格内的数据项拖拽排序,列表拖拽排序效果,实现table动态拖拽,鼠标拖着排序,vue3 element Plus 表格拖曳拖动拖拽 排序,el-table拖拽排序实现,表格内容拖拽重新排序,树形表

✅ 精选推荐文章 1万+

深入理解TVM中的TensorIR抽象

深入理解TVM中的TensorIR抽象 【免费下载链接】tvm Open deep learning compiler stack for cpu, gpu and specialized accelerators 项目地址: h...

gitblog_00289的博客 406

从 ABAP 视角看 JSON :7.40 版本带来的那些改变

摘要:ABAP 对 JSON 的原生支持 随着企业系统与外部 API 的交互增多,ABAP 从 NetWeaver 7.40 开始原生支持 JSON 格式。通过复用现有 XML 基础设施,ABAP 团队引入 JSON-XML 概念,使用 sXML Library 和 IF_SXML=>CO_XT_JSON 常量处理 JSON 数据。开发人员可通过 CALL TRANSFORMATION 语句实现 ABAP 数据与 JSON 的双向转换,大幅简化了与外部系统的数据交互。这种标准化的 JSON 处理方式提

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 180

机器学习实战7-基于机器学习算法预测相亲成功率

大家好,我是微学AI,今天给大家介绍一下机器学习实战7-基于机器学习算法预测相亲成功率,随着社会的发展,大家都忙于事业,对自己的终身大事就耽搁了,相亲是一种传统的寻找伴侣的方式,随着时代的发展,相亲的方式也在不断地改变。在这个过程中,了解相亲双方的信息以及预测相亲是否成功变得越来越重要。本文将介绍如何使用随机森林算法对相亲成功进行预测,通过分析男女双方的房子、车子、长相、家庭条件、父母情况、生活习惯、学历、性格、兴趣等因素,来预测相亲是否成功。

微学AI的博客 3034

机器学习编译MLC 笔记 1-5章(上)

机器学习编译MLC 笔记 1-5章(上)

weixin_44343319的博客 1240

基于树莓派4B设计的厨房环境监测系统_368

本项目设计并实现了一种基于树莓派4B的厨房环境监测系统,提升厨房使用过程中的安全性与智能化水平。系统采用树莓派4B作为主控核心,集成DHT11温湿度传感器、MQ2烟雾传感器、火焰传感器、光敏传感器、水滴检测传感器等多种传感器,实现对厨房环境温湿度、烟雾、火焰、光照与溢水等参数的实时监测,并通过蜂鸣器进行本地报警。系统通过WIFI连接互联网,利用MQTT协议将环境数据上传至华为云物联网平台,实现远程可视化监控。

415

为什么 Twenty 开源 CRM 能取代 Salesforce?从零上手的完整指南

用一套订阅费动辄数千美元、数据还牢牢锁在云端的商业 CRM,是很多中小团队都踩过的坑:**想改一个字段要提工单,想导数据出来要谈合同**。twenty 开源 CRM 就是冲着这个问题来的——它把客户关系管理的核心能力(对象、视图、工作流、AI 助手)全部开放出来,你可以像管理代码一样管理自己的 CRM,免费自托管,数据完全属于自己。 [![twenty 开源 CRM 界面总览](https://

gitblog_00203的博客 401

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

TVM 中文教程:从入门到精通的深度学习编译器指南

TVM是一个开源的深度学习编译器堆栈,它能够将深度学习模型高效地部署到各种硬件后端。作为深度学习领域的重要基础设施,TVM解决了"一次训练,到处部署"的关键挑战。 ## 为什么需要学习TVM 在深度学习应用日益普及的今天,模型部署面临着硬件多样性带来的巨大挑战。不同硬件架构(CPU、GPU、TPU、FPGA等)有着不同的计算特性,而TVM正是解决这一问题的利器。通过学习TVM,开发者可以:

gitblog_00662的博客 884

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

TVM编译入门概念 一

清楚一个概念,onnx模型文件可以直接转换到Relay IR这一层onnx模型文件可以通过这个网站可视化展开哦代码角度看,Relay的基类Expr 就是 tvm.ir基础设施中的RelayIR在tvm/relay/expr.h中可以看到 relay命名空间中Expr指的就是 RelayExprVarNode 是Relay里面的变量VarNode 也会继承自 ExprNode这个类VarNode当中 有vid,type_annotatiton两个成员变量。

qq_43450892的博客 310

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

突破TVM调试瓶颈:Relay Visualizer可视化工具全攻略

当深度学习模型从PyTorch/TensorFlow迁移到TVM部署时,你是否曾面对以下困境: - 复杂的Relay IR模块像黑盒一样难以解析 - 优化Pass后的计算图结构混乱,无法定位性能瓶颈 - 自定义算子集成时难以验证数据流正确性 - 团队协作中无法直观分享模型结构设计 **读完本文你将获得**: - 3分钟上手Relay Visualizer核心功能 - 5种实用可视化方案解决90%

gitblog_00199的博客 501

Win11Debloat 完整指南:3 种安装方式,完成 Windows 11 系统精简、隐私保护与界面定制

Win11Debloat 是一个用 PowerShell(微软自带的脚本引擎)编写的开源 Windows 11 系统优化工具:批量移除预装应用、禁用遥测与推荐广告、定制任务栏和界面,且每项修改都附带对应的回退文件,适合想精简系统、又不想逐条手动改设置的普通用户。 [![Win11Debloat 图形主界面,展示 Windows 11 系统精简与隐私保护的各类勾选项](https://raw.gi

gitblog_00490的博客 837

突破深度学习效率瓶颈:TVM自动微分引擎的梯度优化技术

在深度学习模型训练中,自动微分(Automatic Differentiation,AD)是连接模型定义与参数优化的核心桥梁。传统框架往往将自动微分模块与执行引擎深度耦合,导致在异构硬件上部署时面临性能损耗与兼容性问题。TVM作为开源深度学习编译栈(Open deep learning compiler stack),通过其**Relax IR**与**Tensor IR**双层抽象,实现了兼顾灵

gitblog_00724的博客 326

【TVM 教程】自定义优化

TVM 先已更新到 0.21.0 版本,TVM 中文文档已经和新版本对齐。Apache TVM 是一个深度的深度学习编译框架,适用于 CPU、GPU 和各种机器学习加速芯片。更多 TVM 中文文档可访问 →Apache TVM 的一个主要设计目标是便于自定义优化流程,无论是用于科研探索还是工程开发,都可以灵活迭代优化过程。

HyperAI超神经 516

TVM官方文档翻译入口

TVM官方文档翻译

zx_ros的博客 601

如何快速上手Apache TVM:10分钟完成第一个模型编译的完整教程

Apache TVM(Tensor Virtual Machine)是一个开源的深度学习编译器框架,专门用于优化和部署机器学习模型到各种硬件后端。无论你是想将模型部署到CPU、GPU,还是移动设备或嵌入式系统,TVM都能提供高效的编译解决方案。本文将为你提供一份完整的快速入门指南,帮助你在10分钟内完成第一个模型的编译和运行。 ## 📋 准备工作:安装Apache TVM 在开始使用TVM之

gitblog_00148的博客 394

Apache TVM大型语言模型优化技巧:提升LLM推理性能的10个关键策略

Apache TVM作为一款开源的深度学习编译器,为大型语言模型(LLM)的优化提供了强大支持。通过TVM的编译优化能力,开发者可以显著提升LLM的推理性能,降低延迟并提高吞吐量。本文将分享10个实用的优化策略,帮助你充分利用TVM释放大型语言模型的潜力。 ## 1. 利用TensorIR进行算子级优化 TensorIR是TVM引入的新一代张量程序抽象,专为深度学习算子优化设计。通过Tenso

gitblog_00268的博客 411

tvm教程 -------- 定制优化

可下载并在本地运行 Jupyter notebook。Apache TVM 的一个主要设计目标,是让研究或工程开发都能方便地自定义优化流水线,并快速迭代工程优化。

happyAnger6的专栏 80

工业界真实版「算子开发工程师技能树」:从 CUDA Kernel 到 AI 编译器与硬件映射

算子开发工程师是AI与高性能计算的交叉岗位,核心能力包括计算机体系结构、并行计算模型、线性代数等硬核基础。核心技能涵盖GPU Kernel编程(CUDA/Triton/CUTLASS)、循环调度设计、内存布局优化等。高阶能力包括算子多实现策略、Kernel融合、自动调优及硬件映射(如数据流优化)。工具链涉及性能分析(nsys/nvprof)和IR(MLIR/TVM)。LLM时代新增FlashAttention、KV缓存等专项技能。行业能力分级从基础CUDA编程到架构级编译器设计,反映了从入门到专家的成长路径

Qnesp的博客 507

陈天奇高赞文章:新一代深度学习编译技术变革和展望

来源:机器之心作者:陈天奇陈天奇是机器学习领域著名的青年华人学者之一,本科毕业于上海交通大学ACM班,博士毕业于华盛顿大学计算机系,研究方向为大规模机器学习。在本文中,陈天奇回答了目前深度...

人工智能学家 802
上一篇: 活动预告 | 2023 Meet TVM 开年首聚,上海我们来啦!
下一篇: 用 Real-ESRGAN 拯救座机画质,自制高清版动漫资源
HyperAI超神经
博客等级 码龄7年 8872粉丝 1753原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值