昇思25天学习打卡营第9天|静态图模式的深度剖析与应用指南

目录

背景介绍

动态图模式

静态图模式

静态图模式的使用场景

静态图模式开启方式

基于装饰器的开启方式

基于context的开启方式

静态图的语法约束

JitConfig配置选项

静态图高级编程技巧


背景介绍


        AI 编译框架主要包含两种运行模式,即动态图模式与静态图模式。在默认状况下,MindSpore 是以动态图模式进行运行的,不过同时也支持通过人工操作切换为静态图模式。

动态图模式

        动态图的显著特点在于计算图的构建和计算同步进行(Define by run),这与 Python 的解释执行方式相契合。当在计算图中定义一个 Tensor 时,其值会即刻被计算并确定,所以在调试模型时颇为便捷,能够实时获取中间结果的值。然而,由于所有节点都需保存,致使难以对整个计算图予以优化。

        在 MindSpore 里,动态图模式又称作 PyNative 模式。鉴于动态图的解释执行特性,在脚本开发以及网络流程调试阶段,建议使用动态图模式进行调试。若需手动控制框架采用 PyNative 模式,可通过以下代码来构建网络。

        使用 MindSpore 框架构建了一个简单的神经网络模型,并对输入数据进行了前向传播计算,最后打印输出结果。

        代码如下:

import numpy as np  
import mindspore as ms  
from mindspore import nn, Tensor  
ms.set_context(mode=ms.PYNATIVE_MODE)  # 使用set_context进行动态图模式的配置  
class Network(nn.Cell):  
    def __init__(self):  
        super().__init__()  
        self.flatten = nn.Flatten()  
        self.dense_relu_sequential = nn.SequentialCell(  
            nn.Dense(28*28, 512),  
            nn.ReLU(),  
            nn.Dense(512, 512),  
            nn.ReLU(),  
            nn.Dense(512, 10)  
        )  
  
    def construct(self, x):  
        x = self.flatten(x)  
        logits = self.dense_relu_sequential(x)  
        return logits  
model = Network()  
input = Tensor(np.ones([64, 1, 28, 28]).astype(np.float32))  
output = model(input)  
print(output) 

        分析:首先,成功导入了所需的相关库,这里面有 numpy 以及 mindspore ,还有 mindspore 中的部分重要模块。

        紧接着,定义了一个被命名为 Network 的类,此类别继承自 nn.Cell 。在该类的初始化方法 init 当中,精心定义了一系列的神经网络层,其中涵盖了展平层 Flatten ,以及一个由多层全连接和激活函数所构成的序列 nn.SequentialCell 。

        在 construct 方法里,清晰地定义了前向传播的计算逻辑。具体来说,先是对输入数据实施展平操作,随后通过先前定义好的序列层来进行计算,从而获取到预测的 logits 。

        随后,创建了 Network 类的实例 model ,并且成功生成了一个输入张量 input 。

        最后,将这个输入张量传递进模型展开计算,进而得到输出 output ,并把这一结果予以打印输出

        运行结果:

[[ 0.16246006 -0.11432456  0.04079182  0.16045687  0.01581723  0.00070624  
   0.05681457 -0.02252093 -0.05198406 -0.02421071]  
 [ 0.16246006 -0.11432456  0.04079182  0.16045687  0.01581723  0.00070624  
   0.05681457 -0.02252093 -0.05198406 -0.02421071]  
 [ 0.16246006 -0.11432456  0.04079182  0.16045687  0.01581723  0.00070624  
   0.05681457 -0.02252093 -0.05198406 -0.02421071]  
 [ 0.16246006 -0.11432456  0.04079182  0.16045687  0.01581723  0.00070624  
   0.05681457 -0.02252093 -0.05198406 -0.02421071]  
 [ 0.16246006 -0.11432456  0.04079182  0.16045687  0.01581723  0.00070624  
   0.05681457 -0.02252093 -0.05198406 -0.02421071]  
...  
 [ 0.16246006 -0.11432456  0.04079182  0.16045687  0.01581723  0.00070624  
   0.05681457 -0.02252093 -0.05198406 -0.02421071]  
 [ 0.16246006 -0.11432456  0.04079182  0.16045687  0.01581723  0.00070624  
   0.05681457 -0.02252093 -0.05198406 -0.02421071]  
 [ 0.16246006 -0.11432456  0.04079182  0.16045687  0.01581723  0.00070624  
   0.05681457 -0.02252093 -0.05198406 -0.02421071]  
 [ 0.16246006 -0.11432456  0.04079182  0.16045687  0.01581723  0.00070624  
   0.05681457 -0.02252093 -0.05198406 -0.02421071]  
 [ 0.16246006 -0.11432456  0.04079182  0.16045687  0.01581723  0.00070624  
   0.05681457 -0.02252093 -0.05198406 -0.02421071]] 

静态图模式

        相较于动态图来说,静态图具有一个显著的特点,那便是将计算图的构建与实际的计算过程相互分离(Define and run)。至于静态图模式的运行原理,大家可以参考静态图语法支持的相关内容。

        在 MindSpore 当中,静态图模式还被称作 Graph 模式。处于 Graph 模式之下,借助于图优化、计算图整图下沉等一系列技术,编译器能够针对整个计算图展开全局性的优化操作,进而获取较为出色的性能表现。所以,这种模式相对而言更适合网络结构固定并且对性能要求较高的场景。

        倘若需要手动把控框架采用静态图模式,能够通过如下代码来进行网络的构建:成功定义了一个神经网络模型 Network ,并针对输入数据实施了前向传播以计算输出。接下来,将介绍运用 mindspore 框架构建并运行一个简易神经网络模型的具体方法。

        代码如下:

import numpy as np  
import mindspore as ms  
from mindspore import nn, Tensor  
ms.set_context(mode=ms.GRAPH_MODE)  # 使用set_context进行运行静态图模式的配置  
class Network(nn.Cell):  
    def __init__(self):  
        super().__init__()  
        self.flatten = nn.Flatten()  
        self.dense_relu_sequential = nn.SequentialCell(  
            nn.Dense(28*28, 512),  
            nn.ReLU(),  
            nn.Dense(512, 512),  
            nn.ReLU(),  
            nn.Dense(512, 10)  
        )  
  
    def construct(self, x):  
        x = self.flatten(x)  
        logits = self.dense_relu_sequential(x)  
        return logits  
model = Network()  
input = Tensor(np.ones([64, 1, 28, 28]).astype(np.float32))  
output = model(input)  
print(output)  

        分析:首先导入了必要的库,如 numpy 、mindspore 等,并配置为静态图模式。

        然后定义了一个名为 Network 的类,它继承自 nn.Cell 。在 __init__ 方法中,初始化了一些网络层,包括展平层 nn.Flatten 和一个包含多个全连接层及激活函数的序列 nn.SequentialCell 。

        在 construct 方法中定义了前向传播的计算逻辑,先对输入进行展平操作,然后通过定义的序列层进行计算得到 logits 。

        接着创建了 Network 类的实例 model ,并生成一个输入张量 input 。

        最后将输入通过模型进行计算得到输出 output 并打印。

        运行结果:

[[ 0.08111228 -0.06155853 -0.16565546  0.05599653 -0.10597651 -0.13046513  
   0.05319815  0.13381606  0.15450898 -0.04248318]  
 [ 0.08111228 -0.06155853 -0.16565546  0.05599653 -0.10597651 -0.13046513  
   0.05319815  0.13381606  0.15450898 -0.04248318]  
 [ 0.08111228 -0.06155853 -0.16565546  0.05599653 -0.10597651 -0.13046513  
   0.05319815  0.13381606  0.15450898 -0.04248318]  
 [ 0.08111228 -0.06155853 -0.16565546  0.05599653 -0.10597651 -0.13046513  
   0.05319815  0.13381606  0.15450898 -0.04248318]  
 [ 0.08111228 -0.06155853 -0.16565546  0.05599653 -0.10597651 -0.13046513  
   0.05319815  0.13381606  0.15450898 -0.04248318]  
...  
 [ 0.08111228 -0.06155853 -0.16565546  0.05599653 -0.10597651 -0.13046513  
   0.05319815  0.13381606  0.15450898 -0.04248318]  
 [ 0.08111228 -0.06155853 -0.16565546  0.05599653 -0.10597651 -0.13046513  
   0.05319815  0.13381606  0.15450898 -0.04248318]  
 [ 0.08111228 -0.06155853 -0.16565546  0.05599653 -0.10597651 -0.13046513  
   0.05319815  0.13381606  0.15450898 -0.04248318]  
 [ 0.08111228 -0.06155853 -0.16565546  0.05599653 -0.10597651 -0.13046513  
   0.05319815  0.13381606  0.15450898 -0.04248318]  
 [ 0.08111228 -0.06155853 -0.16565546  0.05599653 -0.10597651 -0.13046513  
   0.05319815  0.13381606  0.15450898 -0.04248318]]  

        

静态图模式的使用场景


        MindSpore 编译器主要聚焦于 Tensor 数据的计算及其微分处理。故而,运用 MindSpore API 以及基于 Tensor 对象的操作,采用静态图编译优化会更为适宜。其他操作虽说能够部分纳入图编译,然而实际的优化效果却较为有限。再者,静态图模式所具有的先编译后执行的特性,致使其存在编译耗时的情况。所以,倘若函数无需多次执行,那么利用静态图来加速或许并无太大意义。

静态图模式开启方式


基于装饰器的开启方式

        MindSpore 提供了 jit 装饰器,能够通过对 Python 函数或者 Python 类的成员函数进行修饰,使其被编译为计算图,借由图优化等技术来提升运行速度。此时,我们能够简便地针对期望进行性能优化的模块实施图编译加速,而模型的其他部分,依旧采用解释执行的方式,从而不会丧失动态图的灵活性。不管全局 context 是设定为静态图模式还是动态图模式,被 jit 修饰的部分始终会以静态图模式运行。

        当需要对 Tensor 的某些运算进行编译加速时,可以在其定义的函数上运用 jit 装饰器,在调用该函数时,此模块会自动被编译成静态图。需要留意的是,jit 装饰器仅能用于修饰函数,无法对类进行修饰。jit 的使用示例如下:

        即使用 MindSpore 框架构建了一个神经网络 Network ,然后使用 ms.jit 装饰器定义了一个名为 run 的函数,在这个函数中创建了 Network 模型实例,并将输入数据 input 传入模型进行计算,最后打印输出结果。

        代码如下:

import numpy as np  
import mindspore as ms  
from mindspore import nn, Tensor  
class Network(nn.Cell):  
    def __init__(self):  
        super().__init__()  
        self.flatten = nn.Flatten()  
        self.dense_relu_sequential = nn.SequentialCell(  
            nn.Dense(28*28, 512),  
            nn.ReLU(),  
            nn.Dense(512, 512),  
            nn.ReLU(),  
            nn.Dense(512, 10)  
        )  
    def construct(self, x):  
        x = self.flatten(x)  
        logits = self.dense_relu_sequential(x)  
        return logits  
  
input = Tensor(np.ones([64, 1, 28, 28]).astype(np.float32))  
@ms.jit  # 使用ms.jit装饰器,使被装饰的函数以静态图模式运行  
def run(x):  
    model = Network()  
    return model(x)  
output = run(input)  
print(output)  

        分析:首先,定义了一个名为 Network 的类,继承自 nn.Cell ,在类中初始化了一些层,包括 Flatten 和一系列的 Dense 与 ReLU 层。

        然后,定义了一个输入 input ,它是一个 Tensor 类型的数据。

        接着,使用 ms.jit 装饰器修饰 run 函数,这意味着在运行 run 函数时,其中的操作会以静态图模式进行优化和执行。

        在 run 函数内部,创建了 Network 模型的实例 model ,并将 input 传入模型计算得到结果并返回。

        最后,将 run 函数的输出打印出来。

        运行结果:

[[ 0.0252679   0.0036834   0.08489509  0.07125469  0.19286017 -0.01487035  
  -0.04551143  0.1177191  -0.00667884  0.02147292]  
 [ 0.0252679   0.0036834   0.08489509  0.07125469  0.19286017 -0.01487035  
  -0.04551143  0.1177191  -0.00667884  0.02147292]  
 [ 0.0252679   0.0036834   0.08489509  0.07125469  0.19286017 -0.01487035  
  -0.04551143  0.1177191  -0.00667884  0.02147292]  
 [ 0.0252679   0.0036834   0.08489509  0.07125469  0.19286017 -0.01487035  
  -0.04551143  0.1177191  -0.00667884  0.02147292]  
 [ 0.0252679   0.0036834   0.08489509  0.07125469  0.19286017 -0.01487035  
  -0.04551143  0.1177191  -0.00667884  0.02147292]  
...  
 [ 0.0252679   0.0036834   0.08489509  0.07125469  0.19286017 -0.01487035  
  -0.04551143  0.1177191  -0.00667884  0.02147292]  
 [ 0.0252679   0.0036834   0.08489509  0.07125469  0.19286017 -0.01487035  
  -0.04551143  0.1177191  -0.00667884  0.02147292]  
 [ 0.0252679   0.0036834   0.08489509  0.07125469  0.19286017 -0.01487035  
  -0.04551143  0.1177191  -0.00667884  0.02147292]  
 [ 0.0252679   0.0036834   0.08489509  0.07125469  0.19286017 -0.01487035  
  -0.04551143  0.1177191  -0.00667884  0.02147292]  
 [ 0.0252679   0.0036834   0.08489509  0.07125469  0.19286017 -0.01487035  
  -0.04551143  0.1177191  -0.00667884  0.02147292]]  

        除使用修饰器外,也可使用函数变换方式调用jit方法,示例如下:

        代码如下:

import numpy as np  
import mindspore as ms  
from mindspore import nn, Tensor  
class Network(nn.Cell):  
    def __init__(self):  
        super().__init__()  
        self.flatten = nn.Flatten()  
        self.dense_relu_sequential = nn.SequentialCell(  
            nn.Dense(28*28, 512),  
            nn.ReLU(),  
            nn.Dense(512, 512),  
            nn.ReLU(),  
            nn.Dense(512, 10)  
        )  
    def construct(self, x):  
        x = self.flatten(x)  
        logits = self.dense_relu_sequential(x)  
        return logits  
input = Tensor(np.ones([64, 1, 28, 28]).astype(np.float32))  
def run(x):  
    model = Network()  
    return model(x)  
run_with_jit = ms.jit(run)  # 通过调用jit将函数转换为以静态图方式执行  
output = run(input)  
print(output)  

        分析:首先导入了所需的库和模块。然后定义了一个名为 Network 的类,它继承自 nn.Cell ,在类的初始化方法 __init__ 中定义了一些层,包括展平层 Flatten 和一个由全连接层 Dense 与激活函数 ReLU 组成的序列 dense_relu_sequential 。

        接着创建了一个输入数据 input 。

        之后定义了一个名为 run 的函数,在函数内部创建了 Network 类的实例 model ,并将输入 x 传入模型进行计算并返回结果。

        然后通过 ms.jit(run) 将 run 函数转换为以静态图方式执行,并将其结果赋值给 run_with_jit 。

        最后调用 run 函数并将输入 input 传入,得到输出并打印。

        总的来说,这段代码构建了一个神经网络模型,并尝试以不同的方式(普通函数和静态图)来运行模型进行计算和输出结果。

        运行结果:

[[-0.26886722 -0.01613193 -0.02503425 -0.06268327  0.1372346   0.08339559  
  -0.05737131 -0.03662169  0.09235285 -0.12165849]  
 [-0.26886722 -0.01613193 -0.02503425 -0.06268327  0.1372346   0.08339559  
  -0.05737131 -0.03662169  0.09235285 -0.12165849]  
 [-0.26886722 -0.01613193 -0.02503425 -0.06268327  0.1372346   0.08339559  
  -0.05737131 -0.03662169  0.09235285 -0.12165849]  
 [-0.26886722 -0.01613193 -0.02503425 -0.06268327  0.1372346   0.08339559  
  -0.05737131 -0.03662169  0.09235285 -0.12165849]  
 [-0.26886722 -0.01613193 -0.02503425 -0.06268327  0.1372346   0.08339559  
  -0.05737131 -0.03662169  0.09235285 -0.12165849]  
...  
 [-0.26886722 -0.01613193 -0.02503425 -0.06268327  0.1372346   0.08339559  
  -0.05737131 -0.03662169  0.09235285 -0.12165849]  
 [-0.26886722 -0.01613193 -0.02503425 -0.06268327  0.1372346   0.08339559  
  -0.05737131 -0.03662169  0.09235285 -0.12165849]  
 [-0.26886722 -0.01613193 -0.02503425 -0.06268327  0.1372346   0.08339559  
  -0.05737131 -0.03662169  0.09235285 -0.12165849]  
 [-0.26886722 -0.01613193 -0.02503425 -0.06268327  0.1372346   0.08339559  
  -0.05737131 -0.03662169  0.09235285 -0.12165849]  
 [-0.26886722 -0.01613193 -0.02503425 -0.06268327  0.1372346   0.08339559  
  -0.05737131 -0.03662169  0.09235285 -0.12165849]]  

        当我们需要对神经网络的某部分进行加速时,可以直接在construct方法上使用jit修饰器,在调用实例化对象时,该模块自动被编译为静态图。示例如下:

        代码如下:

import numpy as np  
import mindspore as ms  
from mindspore import nn, Tensor  
class Network(nn.Cell):  
    def __init__(self):  
        super().__init__()  
        self.flatten = nn.Flatten()  
        self.dense_relu_sequential = nn.SequentialCell(  
            nn.Dense(28*28, 512),  
            nn.ReLU(),  
            nn.Dense(512, 512),  
            nn.ReLU(),  
            nn.Dense(512, 10)  
        )  
    @ms.jit  # 使用ms.jit装饰器,使被装饰的函数以静态图模式运行  
    def construct(self, x):  
        x = self.flatten(x)  
        logits = self.dense_relu_sequential(x)  
        return logits  
input = Tensor(np.ones([64, 1, 28, 28]).astype(np.float32))  
model = Network()  
output = model(input)  
print(output)

        分析:首先,导入了 numpy 库并命名为 np ,导入了 mindspore 库并命名为 ms ,还从 mindspore 库中导入了 nn 和 Tensor 。

        然后,定义了一个名为 Network 的类,它继承自 nn.Cell 。在类的初始化方法 __init__ 中进行了一些基础设置。

        接着,使用 ms.jit 装饰器修饰了 Network 类的 construct 方法,这意味着该方法在运行时会以静态图模式进行优化。

        之后,创建了一个输入数据 input ,它是一个 Tensor 类型。

        再然后,创建了 Network 类的实例 model 。

        最后,将 input 传入 model 进行计算,得到输出 output 并打印出来。

        总的来说,这段代码构建了一个基于 MindSpore 的神经网络模型,并对给定的输入数据进行计算和输出结果。

        运行结果:

[[-0.01447779 -0.02491043 -0.06172827 -0.12281439  0.05957274 -0.28446954  
   0.17217562  0.14563462  0.08131266 -0.02172118]  
 [-0.01447779 -0.02491043 -0.06172827 -0.12281439  0.05957274 -0.28446954  
   0.17217562  0.14563462  0.08131266 -0.02172118]  
 [-0.01447779 -0.02491043 -0.06172827 -0.12281439  0.05957274 -0.28446954  
   0.17217562  0.14563462  0.08131266 -0.02172118]  
 [-0.01447779 -0.02491043 -0.06172827 -0.12281439  0.05957274 -0.28446954  
   0.17217562  0.14563462  0.08131266 -0.02172118]  
 [-0.01447779 -0.02491043 -0.06172827 -0.12281439  0.05957274 -0.28446954  
   0.17217562  0.14563462  0.08131266 -0.02172118]  
...  
 [-0.01447779 -0.02491043 -0.06172827 -0.12281439  0.05957274 -0.28446954  
   0.17217562  0.14563462  0.08131266 -0.02172118]  
 [-0.01447779 -0.02491043 -0.06172827 -0.12281439  0.05957274 -0.28446954  
   0.17217562  0.14563462  0.08131266 -0.02172118]  
 [-0.01447779 -0.02491043 -0.06172827 -0.12281439  0.05957274 -0.28446954  
   0.17217562  0.14563462  0.08131266 -0.02172118]  
 [-0.01447779 -0.02491043 -0.06172827 -0.12281439  0.05957274 -0.28446954  
   0.17217562  0.14563462  0.08131266 -0.02172118]  
 [-0.01447779 -0.02491043 -0.06172827 -0.12281439  0.05957274 -0.28446954  
   0.17217562  0.14563462  0.08131266 -0.02172118]]  

基于context的开启方式

        context模式是一种全局的设置模式。

        代码如下:

import numpy as np  
import mindspore as ms  
from mindspore import nn, Tensor  
ms.set_context(mode=ms.GRAPH_MODE)  # 使用set_context进行运行静态图模式的配置  
class Network(nn.Cell):  
    def __init__(self):  
        super().__init__()  
        self.flatten = nn.Flatten()  
        self.dense_relu_sequential = nn.SequentialCell(  
            nn.Dense(28*28, 512),  
            nn.ReLU(),  
            nn.Dense(512, 512),  
            nn.ReLU(),  
            nn.Dense(512, 10)  
        )  
    def construct(self, x):  
        x = self.flatten(x)  
        logits = self.dense_relu_sequential(x)  
        return logits  
model = Network()  
input = Tensor(np.ones([64, 1, 28, 28]).astype(np.float32))  
output = model(input)  
print(output)  

        分析:首先导入了 numpy 库并简称为 np ,导入了 mindspore 库并简称为 ms ,还从 mindspore 中导入了 nn 和 Tensor 。

        然后使用 ms.set_context(mode=ms.GRAPH_MODE) 配置了 mindspore 的运行环境为静态图模式。

        接着定义了一个名为 Network 的类,继承自 nn.Cell 。在类的初始化方法 __init__ 中进行了一些层的定义,包括展平层和一系列全连接层与激活函数层的组合。

        之后创建了 Network 类的实例 model ,并创建了输入数据 input 。

        最后将 input 传入 model 进行计算得到输出 output ,并将其打印出来。

        总的来说,这段代码构建了一个神经网络模型,并在静态图模式下对输入数据进行处理和得到输出。

        运行结果:

[[ 0.11365249 -0.186111   -0.28579414  0.13091658  0.02833005 -0.17373694  
   0.28168008  0.04766882  0.0583384   0.0371065 ]  
 [ 0.11365249 -0.186111   -0.28579414  0.13091658  0.02833005 -0.17373694  
   0.28168008  0.04766882  0.0583384   0.0371065 ]  
 [ 0.11365249 -0.186111   -0.28579414  0.13091658  0.02833005 -0.17373694  
   0.28168008  0.04766882  0.0583384   0.0371065 ]  
 [ 0.11365249 -0.186111   -0.28579414  0.13091658  0.02833005 -0.17373694  
   0.28168008  0.04766882  0.0583384   0.0371065 ]  
 [ 0.11365249 -0.186111   -0.28579414  0.13091658  0.02833005 -0.17373694  
   0.28168008  0.04766882  0.0583384   0.0371065 ]  
...  
 [ 0.11365249 -0.186111   -0.28579414  0.13091658  0.02833005 -0.17373694  
   0.28168008  0.04766882  0.0583384   0.0371065 ]  
 [ 0.11365249 -0.186111   -0.28579414  0.13091658  0.02833005 -0.17373694  
   0.28168008  0.04766882  0.0583384   0.0371065 ]  
 [ 0.11365249 -0.186111   -0.28579414  0.13091658  0.02833005 -0.17373694  
   0.28168008  0.04766882  0.0583384   0.0371065 ]  
 [ 0.11365249 -0.186111   -0.28579414  0.13091658  0.02833005 -0.17373694  
   0.28168008  0.04766882  0.0583384   0.0371065 ]  
 [ 0.11365249 -0.186111   -0.28579414  0.13091658  0.02833005 -0.17373694  
   0.28168008  0.04766882  0.0583384   0.0371065 ]]  

静态图的语法约束


        在 Graph 模式中,Python 代码并非交由 Python 解释器来执行,而是会先将其编译为静态计算图,后续再对静态计算图予以执行。正因如此,编译器难以对全部的 Python 语法提供支持。MindSpore 的静态图编译器精心维护了 Python 常用语法的子集部分,旨在为神经网络的构建以及训练提供有力支撑。

JitConfig配置选项


        在图模式之下,能够通过运用 JitConfig 配置选项来在一定程度上对编译流程进行自定义。当下,JitConfig 所支持的配置参数具体如下:

        jit_level:其作用是把控优化的等级。

        exec_mode:用于掌控模型的执行方式。

        jit_syntax_level:设定静态图语法的支持级别。

静态图高级编程技巧


        使用静态图高级编程技巧可以有效地提高编译效率以及执行效率,并可以使程序运行的更加稳定。

  运行截图:

  • 30
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值