大模型量化技术(Quantization)可视化指南

顾名思义,大型语言模型的规模通常过于庞大,难以在消费级硬件上运行。这类模型的参数量可达数十亿级别,通常需要配备大容量显存的GPU来加速推理过程。

为此,越来越多的研究聚焦于通过优化训练方式、引入适配器等技术缩小模型规模。其中一项关键技术便是 量化

img

本文将以语言建模为背景,系统介绍量化技术领域,通过逐层剖析核心概念助您建立直观认知。我们将深入解析量化的各类方法、实际应用场景及其底层原理。

作为可视化指南,文中将包含大量图表辅助建立量化技术的直观理解!

第一部分:LLM的核心挑战

LLM 的名称源于其庞大的参数规模。当今主流模型通常包含数十亿参数(主要为 权重),其存储开销极为昂贵。

在推理过程中,激活值由输入数据与权重相乘产生,其规模同样可能非常庞大。

img

因此,我们需要以最高效的方式表示数十亿个数值,最大限度减少存储特定值所需的空间占用。

让我们从基本原理出发,在探讨优化方法之前,先深入理解数值的原始表示方式。

数值表示方法

数值通常以浮点数(计算机科学中称为 floats)形式表示,即带有小数点的正负实数。

这些数值通过「比特位数」(二进制数字)进行编码。IEEE-754 标准定义了如何用比特位数构成三个功能组件来表示数值:符号位指数位 以及 小数位(或称尾数)

img

通过这三个组件的比特值组合,可计算出对应的具体数值:

img

一般而言,分配的比特位数越多,数值表示的精度就越高:

img

内存约束条件

可用的比特位数越多,所能表示的数值范围就越大。

img

特定表示方法所能容纳的数值区间称为 动态范围,而相邻两个数值之间的间隔则称为 精度

img

这些比特位数具备一个实用特性:可精确计算设备存储给定数值所需的内存空间。鉴于8比特(bit)组成1字节(byte),我们可以为大多数浮点表示方法建立基础计算公式。

img 注意:实际应用中,推理过程所需的(V)RAM容量还需考虑其他因素,例如上下文长度和模型架构设计。

现在假设我们有一个包含700亿个参数的模型。大多数模型原生采用32位浮点数(常称为 全精度)表示,仅加载模型就需要占用280GB内存空间。

img

因此,尽可能减少表示模型参数所需的比特位数(在训练过程中也是如此!)变得极具必要性。然而,随着精度的降低,模型的准确性通常也会随之下降。

我们希望在减少数值表示所需比特位数的同时保持准确性……这正是 量化 技术的关键价值所在!

第二部分:量化技术导论

量化的核心目标是将模型参数从高位宽表示(如32位浮点数)转换为低位宽表示(如8位整数)。

img

当减少用于表示原始参数的比特位数时,通常会导致一定程度的精度损失(表现为粒度降低)。

为了直观演示这种效果,我们可以任取一张图像,仅使用8种色彩来呈现它:

img

本图片基于Slava Sidorov 的原作进行修改并适配。

注意放大后的区域相较于原图显得更‘粗糙’,这是因为我们使用了更少的颜色来进行表示。量化的核心目标是通过减少表征原始参数所需的比特位数(类比颜色数量),在最大限度保持参数原始精度的前提下实现高效存储

常用数据类型

首先,我们对比分析常规数据类型与32位(即 全精度FP32)表示方式的差异:

FP16浮点格式

以下展示从32位浮点格式(FP32)转换为16位浮点格式(即 半精度FP16)的实例:

img

值得注意的是,FP16的数值表示范围相较FP32存在显著缩减

BF16

为实现与原始FP32相近的数值覆盖范围,研究者提出了_bfloat16_(BF16)这种“截断式FP32”的浮点格式:

img

BF16虽然与FP16占用相同的存储空间(16位),但其数值表示范围更广,因此被广泛应用于深度学习领域。

INT8

当我们将比特位数进一步降低时,便会进入基于整数的表示方法范畴,而不再使用浮点表示法。以FP32浮点格式转换为8比特的INT8为例,其比特位数将缩减至原始值的四分之一:

img

具体硬件条件下,基于整数的运算速度可能优于浮点运算,但这一优势并非绝对成立。然而,通常当使用较少比特位数时,计算速度会显著提升。

每减少一个比特位,都需要通过映射操作将初始的FP32浮点表示’压缩’到更低位宽中。

实际上,我们无需将完整的FP32范围[-3.4e38, 3.4e38]映射到INT8,只需找到将模型参数的实际数据范围适配到INT8的方法即可。

常见的压缩/映射方法包括 对称量化非对称量化 ,这些都属于 线性映射 的范畴。

接下来我们将具体分析这些从FP32到INT8的量化方法。

对称量化

对称量化的核心原理是将原始浮点数值范围对称地映射到以零为中心的量化空间。通过前文示例可以观察到,量化前后的数值分布始终保持着以零为中心的对称特性。

这种方法的显著特征是:浮点空间中的零值经过量化后,在量化空间中仍精确保持为零值。

img

对称量化的一种典型形式称为绝对值最大(absmax)量化。

给定一组数值,我们以 最高 绝对值(α)作为范围来进行线性映射。

img

注意数值范围[-127, 127]表示受限区间。无约束范围设定为[-128, 127],具体取值取决于所采用的量化方法。

由于该映射是以零为中心的线性变换,其计算公式较为简明。

我们通过以下公式计算比例因子(s):

  • 其中 b 表示目标量化字节数(8字节),
  • α表示输入张量中的最大绝对值,

随后使用计算得到的比例因子 s 对输入值 x 执行量化:

img

代入实际数值后可得以下表达式:

img

若要还原原始FP32浮点格式数值,可使用先前计算的 比例因子s)对量化值进行逆量化。

img

量化解量化过程还原原始值的操作流程如下:

img

可见部分数值(如3.083.02)在INT8量化时均被映射为整数值36。 当将数值解量化恢复为FP32浮点格式时,其精度会有所损失且无法再保持原有的区分度。

这种现象通常被称为 量化误差,可通过计算原始值与解量化值之间的差值来量化评估。

img

通常使用的比特位数越少,产生的量化误差往往越大。

非对称量化

与对称量化不同,非对称量化的数值分布并不以零点为对称中心。该方法将浮点数值范围的最小值(β)和最大值(α)分别映射至量化范围的极值区间。

我们将要深入探讨的方法被称为 零点量化

img

是否注意到零点位置发生了偏移?这正是其被称为 非对称量化 的原因。在[-7.59, 10.8]数值范围内,最小值与最大值到零点的距离呈现不对称性。

基于零点的位置偏移特性,需计算INT8数值范围的零点值以实现精确的线性映射。与对称量化类似,我们仍需计算比例因子(_ s_),但此时使用INT8取值范围[-128, 127]的差值进行计算:

img

需要注意的是,由于该方法要求计算INT8范围内的零点(_ z_)用于权重调整,操作步骤相对复杂。依照既定方法,我们代入量化公式:

img

若要将INT8量化模型解量化回FP32格式,需使用预先计算的比例因子(_ s)和零点参数( z_)

除此之外,解量化过程本身较为直观:

img

将对称量化与非对称量化方法并列对比时,二者的核心差异立即可辨:

img

请注意对称量化天然的零中心特性与非对称量化的偏移分布形成鲜明对比

范围映射与数值截断

在前文案例中,我们已深入解析如何将向量值域映射至低比特位表示的方法尽管这种方法可以映射向量的全部取值范围,但它存在一个显著缺陷——即会产生 离群值

假设存在如下取值的向量:

img

注意观察其中一个值明显大于其他所有值,可视为离群值。若将该向量的全部取值范围进行映射,则所有较小值都会被压缩至相同的低比特表示形式,从而丧失其差异性特征:

img

这正是前文使用的absmax量化方法。需注意的是,若不实施截断操作,非对称量化同样会出现类似现象。

作为替代方案,我们可以选择_截断_特定数值。截断的核心在于重新设定原始值的动态范围,使得所有异常值统一归为相同数值。

如下例所示,若手动将动态范围设定为[-5, 5],该区间外的所有值无论大小都将被统一映射为-127或127:

img

该方法的核心优势在于能大幅降低 正常值域数据 的量化误差。但相应地,异常值数据 的量化误差会增大。

校准过程

本例中展示的是通过主观选择[-5, 5]范围的简易实现方式。该范围的选择过程称为_校准_,其核心目标是寻找既能覆盖最大数据量又能最小化量化误差的最优区间。

需注意,不同类型的参数在执行此校准步骤时存在差异性。

权重(及偏置项)

由于大语言模型(LLM)的权重和偏置项在模型运行前就已确定,因此可将其视为 静态 参数。以Llama 3约20GB的模型文件 为例,其主要构成部分即为权重和偏置项。

img

鉴于偏置项数量级(百万级)远小于权重参数(十亿级),通常采用更高精度(如INT16)存储偏置项,而量化优化的核心目标集中在权重处理。

针对已知且保持静态的权重参数,选择量化范围的校准技术主要包括:

  • 手动选定输入范围的 百分位点
  • 通过优化原始权重与量化权重之间的 均方误差(MSE)进行校准;
  • 最小化原始数据与量化值间的 信息熵(KL散度)。

img

若采用百分位数选择策略,将产生与先前讨论相似的数值截断现象。

激活值

在大型语言模型(LLM)中持续更新的输入通常被称为「激活值」。

img

需要注意的是,这些数值之所以称为激活值,是因为它们通常会通过某些激活函数(如SigmoidReLU)进行处理。

与权重不同,在推理过程中,激活值会随着输入数据的变化而动态改变,因此对其进行精确量化颇具挑战。

由于这些数值会在每个隐藏层处理后更新,我们只有在模型执行推理、输入数据流经网络时才能确定其具体值。

img

总体而言,校准权重和激活值的量化方法可分为两大类:

  • 训练后量化(PTQ)

    • 训练 完成 后量化
  • 量化感知训练(QAT)

    • 训练/微调 过程中 量化

第三部分:训练后量化技术

训练后量化(PTQ)是目前最主流的量化方法之一。该技术要求在模型完成训练,对其参数(含权重和激活值)执行量化操作。

权重 的量化可采用对称量化或非对称量化方法。而 激活值 的量化则需通过模型推理获取其潜在分布,因其数值范围无法预先确定。激活值的量化主要包含两种形式:

  • 动态 量化
  • 静态 量化

动态量化

当数据通过隐藏层后,系统会收集其产生的激活值:

img

基于这些激活值的分布特征,可计算出量化输出所需的 零点 (z)和 比例因子 (s):

img

该过程会在数据每次流经新的网络层时重复执行因此,每个网络层都具有独立的 zs 参数值,从而形成差异化的量化方案。

静态量化

与动态量化不同,静态量化不在推理过程中实时计算 零点 (z)和 比例因子(s),而是采用预先计算的方式。为确定这些参数值,需使用校准数据集输入模型以收集潜在的数据分布:

img

完成数据收集后,即可计算出推理阶段执行量化所需的 sz 参数值。在实际执行推理时,sz 参数值不会实时计算,而是采用全局统一值对所有激活值进行量化处理。

总体而言,动态量化通常具有更高精度,因其专门针对每个隐藏层独立计算 sz 参数值。但这种方式可能增加计算耗时,需实时执行参数值的计算过程。

相较之下,静态量化虽然精度稍逊,但由于已预存固定的 sz 量化参数,执行效率显著更高。

4比特量化技术前沿

实践证明,突破8比特以下的量化存在显著挑战,量化误差会随着比特位数的减少呈指数级增长。当前主要通过智能量化策略实现6比特、4比特乃至2比特的突破(但行业普遍不建议采用低于4比特的方案)。

我们将深入解析HuggingFace社区广泛采用的两种代表性方法:

  • GPTQ(全模型GPU部署方案)
  • GGUF(支持部分层CPU卸载方案)
GPTQ算法

GPTQ算法堪称4比特量化领域最著名的实践方法之一1

该算法采用非对称量化方法,并逐层进行处理:每一层在进入下一层前均独立完成量化:

img

在此逐层量化过程中,算法首先将层的权重转换为逆海森矩阵作为模型损失函数的二阶导数,海森矩阵揭示了模型输出对各个权重变化的敏感程度。简而言之,它实际上反映了层中每个权重的(逆)重要性

与海森矩阵中较小值对应的权重更为关键,因为这些权重的微小扰动可能导致模型性能的显著波动

img

在逆海森矩阵中,数值越低表示该权重越“重要”。

接下来,我们首先对权重矩阵中第一行的权重进行量化,随后执行解量化操作:

img

通过该过程,我们可以计算量化误差(*q*,并利用预先计算的逆海森矩阵()对其进行加权处理。本质上,我们基于权重的重要性创建了一个加权量化误差:

img

接下来,我们将这个加权量化误差重新分配到该行中的其他权重上,从而保持网络的整体功能和输出特性。

例如,针对第二个权重(即0.3()),我们会将量化误差()乘以该权重的逆海森矩阵值()后进行累加:

img

我们可以对当前行中的第三个权重执行相同操作:

img

我们持续迭代执行这种加权量化误差的重新分配过程,直至所有权重值完成量化。

该方法行之有效的原因在于,神经网络中的权重通常具有相互关联性。因此,当某个权重出现量化误差时,相关权重会通过逆海森矩阵(inverse-Hessian)进行协同更新。

注意:研究者 采用了多项优化技巧以提升计算效率和模型性能,包括为海森矩阵引入阻尼因子、实施「惰性批处理」策略,以及采用Cholesky分解进行信息预计算。我们强烈推荐观看该YouTube技术讲解视频 以深入理解本主题。

技术提示:如需针对推理速度进行极致优化的量化方案,请重点关注EXL2 框架的实现。

GGUF格式

虽然GPTQ算法是实现大型语言模型全量GPU部署的优秀量化方案,但在实际硬件条件受限时,此时可借助GGUF格式的层级卸载特性,将模型任意计算层动态分配至CPU执行。2

当显存(VRAM)不足时,该方案允许您同时利用CPUGPU进行协同计算。

GGUF量化方法迭代更新频繁,其具体实现可能因位量化级别的不同而有所差异。然而,其通用量化原理可概括如下:

首先,将神经网络某层的权重矩阵分割为多个’超块’,每个超块包含若干’子块’集合。从这些区块结构中,可提取出比例因子(s)和alpha参数(α):

img

对于特定’子块’的量化处理,可采用先前所述的 absmax 绝对值最大化量化方法。需特别注意,该方法通过将权重值与比例因子(s)相乘实现量化缩放:

img

比例因子虽基于’子块’数据计算得出,但最终需使用’超块’的独立比例因子完成量化过程:

img

这种分层量化机制利用’超块’的比例因子()对’子块’比例因子()进行二次量化。

各比例因子的量化级别可能不同,通常’主’模块的比例因子比’子’模块具有更高的精度。

为便于理解,我们将以三种量化位宽(2位、4位和6位)为例进行说明:

img 技术说明:根据量化类型的不同,需通过附加最小值参数(m)对零点进行校准。这些量化模型的量化方式与比例因子(s)保持一致。

关于所有量化级别的概述,请参考原始拉取请求 。 如需了解基于重要性矩阵的量化方法,请查阅此拉取请求 。

第四部分:量化感知训练

在第三部分中,我们演示了如何在模型训练完成 实施量化操作。该方法的局限性在于:量化过程未与模型实际训练流程相结合。

量化感知训练(QAT)正是为此而设计。区别于训练后量化(PTQ)的事后处理方式,QAT通过在训练 过程中 同步学习量化参数来实现优化。

img

由于量化误差在训练阶段即被纳入优化目标,QAT相比PTQ具有更高的精度优势。具体实现流程如下:

在训练过程中,会引入所谓的「fake」伪量化操作。该过程首先将权重量化至INT4等低精度格式,随后反量化为FP32浮点格式:

img

通过这种方式,模型可以在训练过程中将量化过程纳入考量,包括损失计算和权重更新的全过程。

量化感知训练(QAT)致力于寻找「wide」宽域极小值以降低量化误差,因为「narrow」窄域极小值通常会产生更大的量化误差。

img

例如,假设在反向传播过程中未考虑量化效应。根据梯度下降算法,我们会选择损失值最小的权重参数。然而,若该权重处于「narrow」窄域极小值区域,将会引发较大的量化误差。

相反地,若将量化纳入考量,则会在「wide」宽域极小值区域选择不同的更新权重,从而显著降低量化误差。

img

因此,尽管训练后量化(PTQ)在高精度(如FP32浮点格式)下表现更优,但量化感知训练(QAT)在低精度(如INT4)下的实际部署效果更佳,这正是量化技术追求的目标。

1位大型语言模型时代:比特网络

如先前所述,4位量化已属极小规模,但若进一步压缩至更低位宽会如何?

比特网络 应运而生,其采用单1位量化表示模型权重,每个权重仅取**-11**两种值。3

该方法通过将量化过程深度集成至Transformer架构实现。

值得注意的是,作为多数大型语言模型基石的Transformer架构,其核心计算单元由线性层构成:

img

这些线性层通常以FP16浮点格式等高精度数值表示,且承载了模型绝大部分权重参数。

比特网络通过其创新设计的比特线性层替代传统线性层:

img

比特线性层与标准线性层功能一致,通过权重矩阵与激活值的乘积运算生成输出结果。

相比之下,比特线性层采用1位量化表示模型权重,并利用INT8格式编码激活值:

img

与量化感知训练(QAT)类似,比特线性层在训练过程中会执行’模拟量化’操作,用于评估权重和激活值量化后的效果:

img

技术说明:原论文使用γ作为参数符号,但为保持与本文示例符号体系一致,此处统一采用α。 需特别指出,此处的β参数与零点量化中的定义不同,它表示平均绝对值。

下面我们将分步骤详解比特线性层的实现机制。

权重量化

在训练阶段,权重首先以INT8格式存储,随后通过_符号函数_的基础策略量化为1位精度。

其核心原理是将权重分布中心归零处理:将零值左侧数据统一映射为-1,右侧数据映射为1

img

系统会持续追踪β(平均绝对值**)**参数,该值将用于后续的逆量化过程。

激活值量化

在激活值量化环节,比特线性层运用 绝对值最大化量化 技术,将FP16格式的激活值转换为INT8精度,以满足矩阵乘法(×)运算的高精度要求。

img

系统会持续记录α(最大绝对值)参数,该值将用于后续的逆量化过程。

逆量化

我们持续追踪了α(激活值的最大绝对值)β(权重的平均绝对值),这些参数将帮助我们将激活值解量化回FP16浮点格式。

输出激活值通过{α, γ}参数组进行重新缩放,以将其逆量化为原始精度:

img

至此流程完成!该方法相对简单直观,使得模型仅需用 -11 两个数值即可表征。

应用此方法后,研究者发现模型规模越大,1位量化模型与全精度FP16训练模型之间的性能差异越小。

但此现象仅存在于大型模型(参数量>300亿),较小模型的性能差距仍较为明显。

所有大语言模型均采用1.58比特量化

比特网络1.58b 的提出旨在改进前文所述的扩展性问题4

这种创新方法中,每个权重不仅可以是 -11,现在还可取 0 作为值,从而形成三元权重体系。值得注意的是,仅引入 0 值就显著提升了比特网络的性能,并大幅加速了计算过程。

零值的威力

为何添加0值能产生如此显著的性能提升?其核心机制完全体现在 矩阵乘法 的优化上!

首先,我们需要理解标准矩阵乘法的基本运算原理。在进行输出计算时,需执行权重矩阵与输入向量的乘积运算。下图直观展示了权重矩阵第一层的首次乘积累加运算过程:

img

需要特别指出,该运算包含两个关键步骤:相乘(单个权重与输入值逐元素相乘)和累加(将所有乘积结果求和)。

与之形成对比的是,比特网络1.58b采用的三元权重机制通过以下规则有效规避了乘法运算:

  • 1: 需要累加当前值
  • 0: 舍弃当前值
  • -1:需要减去该数值时

因此,当权重完成1.58位量化后,我们仅需进行加法运算即可:

img

该方案不仅能大幅提升计算速度,还可实现特征筛选功能。

通过将指定权重置零,可直接忽略该参数,避免了传统1位表征必须进行的加减运算。

量化技术

比特网络1.58b采用改进型 绝对值均值量化 方案,此方法基于先前介绍的绝对值最大化量化改进而来。

该方法通过压缩权重参数分布,并基于绝对均值(α)执行数值量化处理。最终将量化结果取整至-101三个离散值:

img

相较原版比特网络,激活值量化机制仅存在一项改进:激活值的缩放范围从原有的[ 0 , 2ᵇ⁻¹ ]区间调整为采用区间[ -2ᵇ⁻¹ , 2ᵇ⁻¹ ],而非使用 绝对值最大化量化 方法。

至此,实现1.58比特量化主要依靠两个关键技术:

  • 引入0值构建三元表示[-1, 0, 1]
  • 针对权重的 绝对值均值量化

通过仅使用计算高效的1.58比特参数,最终我们获得了轻量化模型!

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值