各类深度学习框架详解+深度学习训练环境搭建-GPU版本

目录

前言

一、深度学习框架

TensorFlow

PyTorch

Keras

Caffe

PaddlePaddle

二、深度学习框架环境搭建

1.CUDA部署

CUDA特性

CUDA下载

2.cuDNN

 cuDNN 的主要特性

cuDNN 下载

 3.安装TensorFlow框架

TensorFlow 2

旧版 TensorFlow 1

4.安装PyTorch框架

5.安装Caffe框架

 Windows下载

6.PaddlePaddle


前言

工欲善其事必先利其器,对工具的熟练程度很多时候决定你工程项目的质量和上限。对于人工智能工程师来说,搭建本地深度学习环境来说是比较麻烦的一件事,其中涉及到较多的相关硬件和软件的兼容问题。很多初学者安装的深度学习框架环境仅能够使用CPU运行并没有利用到GPU,关于很多硬件关联的深度学习训练框架并没有清楚的认知,导致配置环境的时候很容易出现各类错误。所以本篇文章主要讲述清楚如何搭建深度学习环境以及框架选择和自己硬件匹配的系统。

如果你发现深度学习看似难以掌握,我将尽力简化知识,将其转化为我们更容易理解的内容。我会确保你能够理解知识并顺利运用到实践中。在后期,我将发布一系列专门解析深度学习框架的文章,但在开始学习之前,我们需要对深度学习的理论知识和实践操作有一定的熟悉度。

作为一个从事数据建模五年的专业人士,我参与了许多数学建模项目,了解各种模型的原理、建模流程和题目分析方法。我希望通过这个专栏让你能够快速掌握各类数学模型、机器学习和深度学习知识,并掌握相应的代码实现。每篇文章都包含实际项目和可运行的代码。我会紧跟各类数模比赛,将最新的思路和代码分享给你,保证你能够高效地学习这些知识。

博主非常期待与你一同探索这个精心打造的专栏,里面充满了丰富的实战项目和可运行的代码,希望你不要错过:专栏链接


一、深度学习框架

深度学习框架还是比较多的,一般来说用PyTorch和EensorFlow的比较多,在一些教程和书籍里面案例也有用Keras和Caffe的,当然最近的国产深度学习框架PaddlePaddle和ModelArts也是使用者比较多。找到适合自己开发习惯以及硬件设备、具备多样功能的深度学习框架十分重要。但是初学者仅是在相应深度学习的书籍或者在其他文章或者网页上看到有关相关深度学习框架的介绍,但是缺乏使用场景和相应测试,就直接安装了。那么我们就先从框架配置的环境入手,一步一步来带大家认清楚深度学习的框架。

TensorFlow

由Google开发的开源深度学习框架,支持各类神经网络和深度学习模型的构建和训练。TensorFlow的一个重要特点是其可移植性。它提供了一个抽象层,使得开发人员可以以统一的方式编写深度学习模型,而不需要过多关注底层硬件细节。TensorFlow可以在各种硬件和平台上运行,包括CPU、GPU、TPU,以及移动设备、服务器等。对于大规模生产环境,TensorFlow提供了高度优化的工具和库,如TFX(TensorFlow Extended)和TF Serving。TensorFlow生态系统涵盖了各种工具、库和扩展,包括TensorBoard、TensorFlow Lite等。

如果你在一个大型企业环境中工作,可能会更偏向TensorFlow。下面我来展示一段利用TensorFlow来展示静态图定义、自动求导和高效的GPU加速计算:

import tensorflow as tf

a = tf.Variable(2.0)  # 将 a 和 b 声明为可训练的变量
b = tf.Variable(3.0)

with tf.GradientTape() as tape:
    c = a * b

grad = tape.gradient(c, [a, b])

with tf.compat.v1.Session() as sess:
    sess.run(tf.compat.v1.global_variables_initializer())  # 初始化变量

    result = sess.run(c)
    print(f'Result: {result}')

    gradient_values = sess.run(grad)
    print(f'Gradient of a: {gradient_values[0]}, Gradient of b: {gradient_values[1]}')

with tf.device('/GPU:0'):
    a = tf.Variable(2.0)
    b = tf.Variable(3.0)
    c = a * b

    with tf.compat.v1.Session() as sess:
        sess.run(tf.compat.v1.global_variables_initializer())

        result = sess.run(c)
        print(f'Result with GPU: {result}')

Result: 6.0
Gradient of a: 3.0, Gradient of b: 2.0
Result with GPU: 6.0

 在TensorFlow 1.x版本中,需要使用tf.Session来运行计算图。虽然在2.x版本中引入了Eager Execution(动态图执行),但仍然需要显式声明。

PyTorch

PyTorch可以说是三大主流框架中最适合初学者学习的了,相较于其他主流框架,PyTorch的简单易用性使其成为初学者们的首选。这样我想要强调的一点是,框架可以类比为编程语言,仅为我们实现项目效果的工具,也就是我们造车使用的轮子,我们重点需要的是理解如何使用Torch去实现功能而不要过度在意轮子是要怎么做出来的,那样会牵扯我们太多学习时间。以后就出一系列专门细解深度学习框架的文章,但是那是较后期我们对深度学习的理论知识和实践操作都比较熟悉才好开始学习,现阶段我们最需要的是学会如何使用这些工具。

PyTorch 使用动态计算图,这使得定义和修改模型变得更加直观和容易理解。这使得初学者可以更快地上手。而且PyTorch 的编程风格非常接近标准的 Python 代码。如果你熟悉 Python,将会更容易学习和使用 PyTorch。PyTorch 允许你使用 Python 控制流语句(如循环和条件语句)来定义模型,这使得构建动态模型结构变得更加容易。

PyTorch 提供了一个友好、直观且容易上手的环境,使得初学者可以更快地开始学习和实践深度学习。当然,最终选择使用哪个框架取决于个人偏好和需求,但对于初学者来说,PyTorch 往往是一个很好的选择。

当使用PyTorch时,你会发现它的动态计算图和直观的API设计使得实验和研究变得非常直观和自由。以下是一个简单的示例,展示了在PyTorch中创建一个简单的神经网络的过程:

import torch
import torch.nn as nn

# 定义一个简单的神经网络
class SimpleNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(SimpleNN, self).__init__()
        self.hidden = nn.Linear(input_size, hidden_size)
        self.relu = nn.ReLU()
        self.output = nn.Linear(hidden_size, output_size)
        
    def forward(self, x):
        out = self.hidden(x)
        out = self.relu(out)
        out = self.output(out)
        return out

# 定义模型、损失函数和优化器
input_size = 10
hidden_size = 5
output_size = 2

model = SimpleNN(input_size, hidden_size, output_size)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

# 生成一些随机数据
X = torch.randn(100, input_size)
y = torch.randint(0, 2, (100,))

# 训练模型
for epoch in range(100):
    optimizer.zero_grad()
    outputs = model(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer.step()

# 在测试集上测试模型
with torch.no_grad():
    test_X = torch.randn(10, input_size)
    predicted = model(test_X)
    _, predicted_labels = torch.max(predicted, 1)
    print(predicted_labels)

这段代码展示了使用PyTorch创建、训练和测试一个简单的神经网络的过程。PyTorch的API设计非常直观,你可以很容易地定义模型、损失函数、优化器,并进行前向传播、反向传播等操作。

此外,PyTorch的动态计算图也使得调试变得更加容易,你可以在运行时动态地修改模型的结构、添加打印语句等。

Keras

Keras是一个高级深度学习框架,它建立在底层深度学习库(如TensorFlow、Theano等)之上,旨在让深度学习任务变得更加快速、简单且易于理解。重要的是Keras提供了一个简单和模块化的API来构建和训练我们需要的神经网络,比如卷积神经网络,循环神经网络等等。还有一个优点就是使用Keras可以不用关心大部分函数实现的复杂细节。

Keras可以运行在多种深度学习引擎(后端)上,包括TensorFlow、Theano和CNTK等。这意味着你可以在不同的后端之间无缝切换,以满足特定需求。Keras支持多种深度学习任务,包括分类、回归、目标检测、文本处理等。它也支持了许多常用的深度学习技术,如卷积神经网络(CNN)、循环神经网络(RNN)等。

但是Keras是一个高级抽象的框架,对于一些需要自定义层或者更底层的操作的任务,可能不如直接使用TensorFlow或PyTorch灵活。由于Keras是建立在其他深度学习引擎之上的,可能在某些情况下性能会略逊于直接使用这些引擎。也就是可能会在一些新的深度学习技术或模型架构的支持上略显滞后,因为它依赖于底层引擎的更新。

同样我们用Keras来搭建一个简单的网络,相比其他深度学习框架搭建代码,很容易看到其优势:

# 导入Keras及相关模块
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

# 创建一个简单的线性模型
model = Sequential([
    # 注意这里的input_shape修改为(784,)
    Dense(64, activation='relu', input_shape=(784,)),
    Dense(64, activation='relu'),
    Dense(10, activation='softmax')
])

# 编译模型
model.compile(optimizer='adam', 
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# 加载数据集(以MNIST手写数字识别为例)
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
# 将图像展平
x_train = x_train.reshape((x_train.shape[0], -1))
x_test = x_test.reshape((x_test.shape[0], -1))
# 训练模型
model.fit(x_train, y_train, epochs=1)

# 评估模型
test_loss, test_acc = model.evaluate(x_test, y_test)

print(f"Test accuracy: {test_acc}")

 通过Keras,我们可以通过简单的API设计来快速构建模型,使用高级抽象的方式来定义网络结构和训练流程,使得深度学习变得更加直观、容易上手。同时,Keras提供了丰富的优化器、损失函数和评估指标,使得模型的训练和评估变得简单而便捷。

Caffe

Caffe(Convolutional Architecture for Fast Feature Embedding)是一个由伯克利人工智能研究实验室(BAIR)开发的深度学习框架。它是一个适用于卷积神经网络(CNN)的高效且灵活的工具,特别擅长图像分类、目标检测等计算机视觉任务。

Caffe主要用C++编写,使其运行效率非常高。它还提供了Python接口,方便用户进行快速原型设计和实验。Caffe提供了许多可视化工具,如网络可视化、特征可视化等,方便用户理解和调试模型。Caffe 只支持python2.7和3.5。想要编译caffe需要vs2013和vs2015,并且cpu版和gpu版不通用。因此不推荐大家使用Caffe来学习深度学习。

PaddlePaddle

PaddlePaddle(飞浆)是百度开发的国产深度学习框架,用PaddlePaddle的好处是可以用AI Studio平台提供的GPU算力进行模型训练,不仅节约时间而且还是免费的,PaddlePaddle也提供了像PaddleSeg等一些套件,对于新手上手深度学习模型的项目很友好。当然,其它的框架也可使用网上的一些算力平台进行模型的训练,对初学者十分友好,前期没有训练环境也可以使用,但是使用飞桨平台就无法使用Jupyter Notebook去调用其他深度学习框架了,会和PaddlePaddle冲突,不过你不用他的Jupyter就没问题,可以自己去集成环境。

PaddlePaddle编码风格是和PyTorch差不多的,通过使用paddle.nn.Sequential组网,我们依旧以深度学习里的 Hello World 任务来展现PaddlePaddle的使用特性和编码风格:

import paddle
import numpy as np
from paddle.vision.transforms import Normalize

transform = Normalize(mean=[127.5], std=[127.5], data_format='CHW')
# 下载数据集并初始化 DataSet
train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)

# 模型组网并初始化网络
lenet = paddle.vision.models.LeNet(num_classes=10)
model = paddle.Model(lenet)

# 模型训练的配置准备,准备损失函数,优化器和评价指标
model.prepare(paddle.optimizer.Adam(parameters=model.parameters()), 
              paddle.nn.CrossEntropyLoss(),
              paddle.metric.Accuracy())

# 模型训练
model.fit(train_dataset, epochs=5, batch_size=64, verbose=1)
# 模型评估
model.evaluate(test_dataset, batch_size=64, verbose=1)

# 保存模型
model.save('./output/mnist')
# 加载模型
model.load('output/mnist')

# 从测试集中取出一张图片
img, label = test_dataset[0]
# 将图片shape从1*28*28变为1*1*28*28,增加一个batch维度,以匹配模型输入格式要求
img_batch = np.expand_dims(img.astype('float32'), axis=0)

# 执行推理并打印结果,此处predict_batch返回的是一个list,取出其中数据获得预测结果
out = model.predict_batch(img_batch)[0]
pred_label = out.argmax()
print('true label: {}, pred label: {}'.format(label[0], pred_label))
# 可视化图片
from matplotlib import pyplot as plt
plt.imshow(img[0])
The loss value printed in the log is the current step, and the metric is the average value of previous steps.
Epoch 1/5
step 938/938 [==============================] - loss: 0.0519 - acc: 0.9344 - 14ms/step          
Epoch 2/5
step 938/938 [==============================] - loss: 0.0239 - acc: 0.9767 - 14ms/step          
Epoch 3/5
step 938/938 [==============================] - loss: 0.0416 - acc: 0.9811 - 14ms/step          
Epoch 4/5
step 938/938 [==============================] - loss: 0.0084 - acc: 0.9837 - 14ms/step          
Epoch 5/5
step 938/938 [==============================] - loss: 0.0838 - acc: 0.9860 - 14ms/step          
Eval begin...
step 157/157 [==============================] - loss: 1.7577e-04 - acc: 0.9844 - 6ms/step         
Eval samples: 10000
true label: 7, pred label: 7

二、深度学习框架环境搭建

一般来说环境搭建都会分CPU版本和GPU版本我们平时直接pip install pytorch/tensorflow==版本号 - i 源,默认下载的都是CPU版本的,训练数据时可以看到你的CPU占用很高,GPU不运作。我们进行深度学习实验的时候,一定要了解直接python的版本和CUDA的版本,下载GPU版本的pytorch/tensorflow,需要下载CUDA和cuDNN。我们下载的pytorch/tensorflow、CUDA、cuDNN 都要严格按照版本来下载,以免出错。查看CUDA的版本,可以通过在终端输入指令:

nvidia-smi

 这里要注意CUDA的版本,我们需要根据CUDA版本去选择兼容的深度学习框架。

1.CUDA部署

CUDA(Compute Unified Device Architecture)是由 NVIDIA 公司推出的一种并行计算平台和应用程序接口(API)。它使开发者能够使用通用的 C/C++ 编程语言来利用 NVIDIA GPU 的并行计算能力,从而加速计算密集型应用程序。

CUDA特性

  • 并行计算架构:CUDA 构建在 NVIDIA GPU 的并行计算架构之上,允许大规模的并行化处理。这使得它在许多科学计算、深度学习、图形渲染等领域发挥了重要作用。
  • C/C++ 编程模型:CUDA 使用了一种类似于标准 C 语言的编程模型,开发者可以使用熟悉的语言进行 GPU 编程。
  • 并行编程模型:CUDA 引入了线程层次的并行模型,开发者可以利用线程、线程块和网格来实现不同粒度的并行计算。
  • GPU 加速库:CUDA 提供了一系列的 GPU 加速库,涵盖了数学运算、线性代数、图像处理等各个领域,方便开发者高效地利用 GPU 资源。
  • 支持异构计算:CUDA 允许 CPU 和 GPU 协同工作,形成异构计算系统,充分发挥 CPU 和 GPU 各自的优势。
  • 深度学习框架支持:许多深度学习框架(如 TensorFlow、PyTorch)提供了 CUDA 加速的实现,可以在 GPU 上高效运行深度学习模型。
  • 高性能计算:CUDA 提供了对 GPU 硬件的底层访问,使得开发者能够实现高度优化的并行计算算法,从而获得极高的性能。

CUDA下载

首先进入CUDA官网:CUDA Toolkit Archive

选择想要下载的版本:

选择对应OS和版本,比如我下载的是CUDA Toolkit 12.3,系统是Windows,版本是Windows11。

下载完之后我们还需要下载cuDNN。

2.cuDNN

NVIDIA CUDA® 深度神经网络库 (cuDNN) 是一个 GPU 加速的深度神经网络基元库,能够以高度优化的方式实现标准例程(如前向和反向卷积、池化层、归一化和激活层)。cuDNN 可加速广泛应用的深度学习框架,包括我们以上提到的深度学习框架。借助 cuDNN,研究人员和开发者可以专注于训练神经网络及开发软件应用,而不必花时间进行低层级的 GPU 性能调整。

 cuDNN 的主要特性

  • 为各种常用卷积实现了 Tensor Core 加速,包括 2D 卷积、3D 卷积、分组卷积、深度可分离卷积以及包含 NHWC 和 NCHW 输入及输出的扩张卷积
  • 为诸多计算机视觉和语音模型优化了内核,包括 ResNet、ResNext、EfficientNet、EfficientDet、SSD、MaskRCNN、Unet、VNet、BERT、GPT-2、Tacotron2 和 WaveGlow
  • 支持 FP32、FP16、BF16 和 TF32 浮点格式以及 INT8 和 UINT8 整数格式
  • 4D 张量的任意维排序、跨步和子区域意味着可轻松集成到任意神经网络实现中
  • 能为各种 CNN 体系架构上的融合运算提速

cuDNN 下载

下载的时候需要注意刚刚下载的CUDA版本:

 下载完成后,解压到之前的NVIDIA GPU中,以个人的情况,一般路径在:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0 里面,我下载的版本是11.0既选择11.0的版本对应的cuDNN。

之后需要添加环境变量即可:

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\bin

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\libnvvp

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.0\lib\x64

 3.安装TensorFlow框架

下载框架之前需要清楚是否具备GPU环境和硬件支撑,如果没有的话下载CPU版本。如果想要从CPU版本转为GPU版本,需要将原来的CPU版本卸载。

安装 TensorFlow

TensorFlow 2

  • tensorflow:支持 CPU 和 GPU的最新稳定版(适用于 Ubuntu 和 Windows)
  • tf-nightly:预览 build(不稳定)。Ubuntu 和 Windows 均包含 GPU支持。

旧版 TensorFlow 1

对于 TensorFlow 1.x,CPU 和 GPU 软件包是分开的:

  • tensorflow==1.15:仅支持 CPU 的版本
  • tensorflow-gpu==1.15:支持GPU的版本(适用于 Ubuntu 和 Windows)

一般下载的话,有PIP,Conda,Docker下载方式可供选择。下载之前我们主要要根据自己的cuDNN和CUDA版本安装:

 然后使用PIP下载即可:

pip install tensorflow_gpu==2.4.0 -i https://pypi.doubanio.com/simple

 我这里适配的是2.4.0的版本,通过以上命令下载即可。

4.安装PyTorch框架

之前有安装过PyTorch如果运行不了的推荐卸载以免产生不必要的问题,同理TensorFlow也是一样:

    pip uninstall temsorflow
    pip uninstall pytorch

选择历史版本的PyTorch再下载,可以用PIP和Conda两种方式下载:

INSTALLING PREVIOUS VERSIONS OF PYTORCH

 

 选择对应版本的PyTorch现在即可。

5.安装Caffe框架

Caffe框架安装起来比较麻烦,存在很多和自身环境冲突的问题,该框架限定的Python只有2.7和3.5,因此如果你要下载Caffe需要新建一个虚拟Python环境,而且如果你之前有装CUDA的话你需要注意注意是否有冲突。

下载地址:

Caffe下载地址

主要你系统的版本,在分支里面选择对应的版本:

 如果是Windows就选择Windows,如果是Linux就选择master。下载完整个文件之后,需要注意我们要预编译二进制文件,预构建的二进制文件可以从appveyor上的最新CI构建下载,用于以下配置:

 Windows下载

Windows下载需要依赖:

  • Visual Studio 2013或2015从技术上讲,只需要VS C/C++编译器(cl.exe)
  • CMake 3.4或更高版本(支持Visual Studio和Ninja生成器)
  • pycaffe接口的Python需要是Anaconda Python 2.7或3.5 x64(或Miniconda)
  • 用于matcaffe接口的Matlab。
  • CUDA 7.5 or 8.0 (use CUDA 8 if using Visual Studio 2015)
  • cuDNN v5

如果以上存在和之前的深度学习框架冲突的话就不必要装Caffe了,得不尝试。以后实在存在一定的应用场景再考虑切换虚拟环境安装,初学者不应该花费过多时间用到安装环境上面。

安装完以上依赖后我们需要使用指令

build_win.cmd

 一般来说这里都会弹出错误:

File "D:\anaconda3\lib\subprocess.py", line 1207, in _execute_child startupinfo) FileNotFoundError: [WinError 2] 系统找不到指定的文件。

这里是因为python的指令系统查找不到cmd命令,需要我们自己加上去。需要修改Makefile.config文件:

1.将
#USE_CUDNN := 1
修改成: 
USE_CUDNN := 1
 
2.将
#OPENCV_VERSION := 3 
修改为: 
OPENCV_VERSION := 3
 
3.将
#WITH_PYTHON_LAYER := 1 
修改为 
WITH_PYTHON_LAYER := 1
 
4.
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include
LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib 
修改为: 
INCLUDE_DIRS := $(PYTHON_INCLUDE) /usr/local/include /usr/include/hdf5/serial
LIBRARY_DIRS := $(PYTHON_LIB) /usr/local/lib /usr/lib /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/hdf5/serial       
 
5.我这里使anaconda的python,不使用系统自带的。
 
 
6.将前两行删除
CUDA_ARCH := -gencode arch=compute_30,code=sm_20 \
             -gencode arch=compute_35,code=sm_21 \
             -gencode arch=compute_30,code=sm_30 \
             -gencode arch=compute_35,code=sm_35 \
             -gencode arch=compute_50,code=sm_50 \
             -gencode arch=compute_52,code=sm_52 \
             -gencode arch=compute_61,code=sm_61
变成
CUDA_ARCH := -gencode arch=compute_30,code=sm_30 \
             -gencode arch=compute_35,code=sm_35 \
             -gencode arch=compute_50,code=sm_50 \
             -gencode arch=compute_52,code=sm_52 \
             -gencode arch=compute_61,code=sm_61
 
7.注释掉
#PYTHON_INCLUDE := /usr/include/python2.7 \
                /usr/lib/python2.7/dist-packages/numpy/core/include
 
把anancoda中python放开
ANACONDA_HOME := $(HOME)/anaconda3
PYTHON_INCLUDE := $(ANACONDA_HOME)/include \
                $(ANACONDA_HOME)/include/python3.6m \
                $(ANACONDA_HOME)/lib/python3.6/site-packages/numpy/core/include \

修改 caffe 目录下的 Makefile 文件:

将:
NVCCFLAGS +=-ccbin=$(CXX) -Xcompiler-fPIC $(COMMON_FLAGS)
替换为:
NVCCFLAGS += -D_FORCE_INLINES -ccbin=$(CXX) -Xcompiler -fPIC $(COMMON_FLAGS)
 
将:
LIBRARIES += glog gflags protobuf boost_system boost_filesystem m hdf5_hl hdf5
改为:
LIBRARIES += glog gflags protobuf boost_system boost_filesystem m hdf5_serial_hl hdf5_serial

如果以上任何一个环境都出现报错则不推荐继续安装Caffe。

6.PaddlePaddle

百度飞桨的深度学习环境安装文档已经写的十分详细了:PaddlePaddle安装指南

有官方中文安装文档。


  • 52
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 66
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 66
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

fanstuck

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值