MMDeploy部署实战系列【第二章】:mmdeploy安装及环境搭建

MMDeploy部署实战系列【第二章】:mmdeploy安装及环境搭建

⭐️ ⭐️ ⭐️ 这个系列是一个随笔,是我走过的一些路,有些地方可能不太完善。如果有那个地方没看懂,评论区问就可以,我给补充。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

目录:

0️⃣ mmdeploy源码安装 (转换faster rcnn r50/yolox为tensorrt,并进行推理)_gy77

内容:一文包含了在Linux系统下安装mmdeploy模型转换环境,模型转换为TensorRT,在Linux,Windows下模型推理,推理结果展示。

MMDeploy部署实战系列

1️⃣ MMDeploy部署实战系列【第一章】:Docker,Nvidia-docker安装_gy77

内容:docker/nvidia-docker安装,docker/nvidia-docker国内源,docker/nvidia-docker常用命令。

2️⃣ MMDeploy部署实战系列【第二章】:mmdeploy安装及环境搭建_gy77

内容:mmdeploy环境安装三种方法:源码安装,官方docker安装,自定义Dockerfile安装。

3️⃣ MMDeploy部署实战系列【第三章】:MMdeploy pytorch模型转换onnx,tensorrt_gy77

内容:如何查找pytorch模型对应的部署配置文件,模型转换示例:mmcls:resnext50,mmdet:yolox-s,faster rcnn50。

4️⃣ MMDeploy部署实战系列【第四章】:onnx,tensorrt模型推理_gy77

内容:在linux,windows环境下推理,Windows下推理环境安装,推理速度对比,显存对比,可视化展示。

5️⃣ MMDeploy部署实战系列【第五章】:Windows下Release x64编译mmdeploy(C++),对TensorRT模型进行推理_gy77

内容:Windows下环境安装编译环境,编译c++ mmdeploy,编译c++ mmdeploy demo,运行实例。

6️⃣ MMDeploy部署实战系列【第六章】:将编译好的MMdeploy导入到自己的项目中 (C++)_gy77

内容:Windows下环境导入我们编译好的mmdeploy 静态/动态库。

下面是正文:


mmdeploy安装

分以下三种方法:源码安装,官方docker安装,自定义Dockerfile安装。

docker安装是官方最推荐的。

我刚开始用的官方docker安装,想着出错概率最小,也不用担心兼容性问题。但是我leader给我的部署任务不仅要转换成tensorrt模型,还要部署到triton。这就是个大坑,triton对很多包的版本都有要求,mmdeploy docker里的包你虽然可以修改版本,但也会很麻烦。所以刚开始走了很多弯路,以至于最后也没有triton部署成功(mmdeploy支持tensorrt8.2.3.0,triton对应tensorrt8.2.3.0的版本要求是Ubantu20.04,我当时是18.04,可能还要重装系统)。

对docker没有那么熟悉,所以我最后采用了源码安装,中间也没有什么大错,很顺利。

mmdeploy安装(源码安装),模型转换

参考官方文档: 操作概述 — mmdeploy 0.6.0 文档

本文的主要内容都来自官方文档,只不过是把版本细化了,

GPU: RTX 2060
Driver:455.23.05
Ubantu:18.04
Cuda:11.1
Cudnn:8.2.1(系统的cuda环境下是8.2.1,mmdeploy虚拟环境下是8.0.0.5)
Python:3.7
Pytorch:1.8.0
torchvision:0.9.0
mmdeploy:0.5.0
Tensorrt:8.2.3.0

我的所有的dir

MMDET_DIR : /home/xbsj/gaoying/mmdetection
MMDEPLOY_DIR: /home/xbsj/gaoying/mmdeploy
WORK_DIR : /home/xbsj/gaoying/mmdeploymmdeploy_models/faster_rcnn

准备工作

对于端到端的模型转换和推理,MMDeploy 依赖 Python 3.6+ 以及 PyTorch 1.5+。

1️⃣ 创建并激活 conda 环境
conda create -n mmdeploy python=3.7 -y
conda activate mmdeploy
2️⃣ 安装 PyTorch

Model Converter 的 torch2onnx 功能依赖它。在 GPU 环境下(这里我们以 Ubuntu 18.04 CUDA 11.1 为基础),您可以使用如下方式安装 PyTorch 1.8:

conda install pytorch==1.8.0 torchvision==0.9.0 cudatoolkit=11.1 -c pytorch -c conda-forge
3️⃣ 安装cuda和cudnn

安装cuda 11.1:CUDA Toolkit 11.1 Update 1 Downloads | NVIDIA Developer

安装过程中几个注意的点:第一个页面选continue,第二个页面输入accept,第三个页面在驱动那个选项按空格把x去掉,也就是不安装驱动。然后install。第四个页面选择install。

wget https://developer.download.nvidia.com/compute/cuda/11.1.1/local_installers/cuda_11.1.1_455.32.00_linux.run
sudo sh cuda_11.1.1_455.32.00_linux.run

安装cudnn8.2.1:Download cuDNN v8.2.1 (June 7th, 2021), for CUDA 11.x

https://developer.nvidia.com/compute/machine-learning/cudnn/secure/8.2.1.32/11.3_06072021/cudnn-11.3-linux-x64-v8.2.1.32.tgz 在网址选择版本 后下载,上传到服务器,并解压。然后复制到cuda目录下

tar -zxvf cudnn-11.3-linux-x64-v8.2.1.32.tgz

# 复制cudnn头文件
sudo cp cuda/include/* /usr/local/cuda/include/
# 复制cudnn的库
sudo cp cuda/lib64/* /usr/local/cuda/lib64/
# 添加可执行权限
sudo chmod +x /usr/local/cuda/include/cudnn.h
sudo chmod +x /usr/local/cuda/lib64/libcudnn*

# 检查cudnn版本
cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2
4️⃣ 安装 mmcv-full
python -m pip install mmcv-full==1.5.0 -f https://download.openmmlab.com/mmcv/dist/cu111/torch1.8.0/index.html
5️⃣ 安装 MMDeploy 和 SDK

从 v0.5.0 之后,MMDeploy 开始提供预编译包。您可以根据目标软硬件平台,从这里选择并下载预编译包。在 NVIDIA 设备上,我们推荐使用 MMDeploy-TensoRT 预编译包:

wget https://github.com/open-mmlab/mmdeploy/releases/download/v0.5.0/mmdeploy-0.5.0-linux-x86_64-cuda11.1-tensorrt8.2.3.0.tar.gz

tar -zxvf mmdeploy-0.5.0-linux-x86_64-cuda11.1-tensorrt8.2.3.0.tar.gz

cd mmdeploy-0.5.0-linux-x86_64-cuda11.1-tensorrt8.2.3.0

python -m pip install dist/mmdeploy-0.5.0-py37-none-linux_x86_64.whl
python -m pip install sdk/python/mmdeploy_python-0.5.0-cp37-none-linux_x86_64.whl

# vim ~/.bashrc 配置环境变量,添加下面,根据自己的目录修改,最后source ~/.bashrc  使生效。
export LD_LIBRARY_PATH=/home/xbsj/gaoying/lib/mmdeploy-0.5.0-linux-x86_64-cuda11.1-tensorrt8.2.3.0/sdk/lib:$LD_LIBRARY_PATH            # 改为自己的目录

cd ..
6️⃣ 安装预编译包要求的推理后端 TensorRT

在本例中,我们需要安装 TensorRT(含 cuDNN)推理引擎。因在 NVIDIA 官网下载软件包,必须要登录认证,所以请预先登录并下载所需的 TensorRTcuDNN请注意: TensorRT 版本、cuDNN 版本要和 CUDA 版本匹配

下载完毕后,您可以参考如下方法安装。这里,我们以 TensorRT 8.2.3.0、cuDNN 8.2 为例:

# !!! 从 NVIDIA 官网下载 与 cuda toolkit 匹配的 tensorrt 到当前的工作目录
tar -zxvf TensorRT-8.2.3.0.Linux.x86_64-gnu.cuda-11.4.cudnn8.2.tar.gz

python -m pip install TensorRT-8.2.3.0/python/tensorrt-8.2.3.0-cp37-none-linux_x86_64.whl 
python -m pip install pycuda

# vim ~/.bashrc 配置环境变量,添加下面两行,根据自己的目录修改,最后source ~/.bashrc  使生效。
export TENSORRT_DIR=/home/xbsj/gaoying/lib/TensorRT-8.2.3.0
export LD_LIBRARY_PATH=${TENSORRT_DIR}/lib:$LD_LIBRARY_PATH


# !!! 从 NVIDIA 官网下载与 cuda toolkit,tensorrt 匹配的 cudnn 到当前的工作目录
tar -zxvf cudnn-11.3-linux-x64-v8.2.1.32.tgz
mv cuda cudnn821_cuda111

# vim ~/.bashrc 配置环境变量,添加下面两行,根据自己的目录修改,最后source ~/.bashrc  使生效。
export CUDNN_DIR=/home/xbsj/gaoying/lib/cudnn821_cuda111
export LD_LIBRARY_PATH=$CUDNN_DIR/lib64:$LD_LIBRARY_PATH

模型转换

Faster RCNN

在准备工作就绪后,我们可以使用 MMDeploy 中的工具 deploy.py,将 OpenMMLab 的 PyTorch 模型转换成推理后端支持的格式。

MMDetection 中的 Faster R-CNN 为例,我们可以使用如下命令,将 PyTorch 模型转换成可部署在 NVIDIA GPU 上的 TenorRT 模型:

# 克隆 mmdeploy 仓库。转换时,需要使用 mmdeploy 仓库中的配置文件,建立转换流水线
git clone --recursive https://github.com/open-mmlab/mmdeploy.git
python -m pip install -r mmdeploy/requirements/runtime.txt


# 克隆 mmdetection 仓库。转换时,需要使用 mmdetection 仓库中的模型配置文件,构建 PyTorch nn module
python -m pip install mmdet==2.24.0
git clone https://github.com/open-mmlab/mmdetection.git

# 下载 Faster R-CNN 模型权重
cd ./mmdetection/checkpoints
wget https://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth -O faster_rcnn_r50_fpn_1x_coco.pth

# 设置工作路径
cd ../../mmdeploy
mkdir mmdeploy_models
mkdir mmdeploy_models/faster_rcnn

# 执行转换命令,实现端到端的转换[[模板]]
python ${MMDEPLOY_DIR}/tools/deploy.py \
    ${MMDEPLOY_DIR}/configs/mmdet/detection/detection_tensorrt_dynamic-320x320-1344x1344.py \
    ${MMDET_DIR}/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py \
    ${CHECKPOINT_DIR}/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth \
    ${MMDET_DIR}/demo/demo.jpg \
    --work-dir ${WORK_DIR} \
    --device cuda:0 \
    --dump-info

# 执行转换命令,实现端到端的转换
python tools/deploy.py configs/mmdet/detection/detection_tensorrt_dynamic-320x320-1344x1344.py ../mmdetection/configs/faster_rcnn/faster_rcnn_r50_fpn_1x_coco.py ../mmdetection/checkpoints/faster_rcnn_r50_fpn_1x_coco.pth ../mmdetection/demo/demo.jpg --work-dir mmdeploy_models/faster_rcnn/ --device cuda:0 --dump-info

${MMDEPLOY_DIR}/tools/deploy.py 是一个方便模型转换的工具。您可以阅读 如何转换模型 了解更多细节。

detection_tensorrt_dynamic-320x320-1344x1344.py 是一个参数配置文件。该文件的命名遵循如下规则:

<任务名>_<推理后端>-[后端特性]_<动态模型支持>.py

可以很容易的通过文件名来确定最适合的那个配置文件。如果您希望定制自己的转换配置,可以参考如何编写配置文件修改参数。

yolox
# 下载 YOLOX 模型权重
cd ./mmdetection/checkpoints
wget https://download.openmmlab.com/mmdetection/v2.0/yolox/yolox_s_8x8_300e_coco/yolox_s_8x8_300e_coco_20211121_095711-4592a793.pth -O /yolox_s_8x8_300e_coco.pth

# 执行转换命令,实现端到端的转换
python tools/deploy.py configs/mmdet/detection/detection_tensorrt_dynamic-320x320-1344x1344.py ../mmdetection/configs/yolox/yolox_s_8x8_300e_coco.py ../mmdetection/checkpoints/yolox_s_8x8_300e_coco.pth ../mmdetection/demo/demo.jpg --work-dir mmdeploy_models/yolox_s --device cuda:0 --dump-info

mmdeploy安装(Dockfile安装,国内加速优化)

方法参考:end2end.engine to Triton · Issue #465 · open-mmlab/mmdeploy (github.com)

1️⃣ 克隆mmdeploy

我给的是镜像加速的mmdeploy git源,妈妈再也不用担心我git clone超时了。

git clone https://api.mtr.pub/open-mmlab/mmdeploy.git
2️⃣ 构建Dockerfile文件
# 以 GPU 为例
cd mmdeploy/docker
vim Dockerfile.mmdeploy

Dockerfile.mmdeploy文件内容如下:

FROM nvcr.io/nvidia/tensorrt:21.04-py3

ARG CUDA=11.3
ARG PYTHON_VERSION=3.8
ARG TORCH_VERSION=1.11.0
ARG TORCHVISION_VERSION=0.12.0
ARG ONNXRUNTIME_VERSION=1.11.1
ARG MMCV_VERSION=1.5.0
ARG PPLCV_VERSION=0.6.2
ENV FORCE_CUDA="1"

ENV DEBIAN_FRONTEND=noninteractive

### change the system source for installing libs
ARG USE_SRC_2104=false
RUN if [ ${USE_SRC_2104} == true ] ; \
    then \
        sed -i s/archive.ubuntu.com/mirrors.aliyun.com/g /etc/apt/sources.list ; \
        sed -i s/security.ubuntu.com/mirrors.aliyun.com/g /etc/apt/sources.list ; \
        echo "Use aliyun source for installing libs" ; \
    else \
        echo "Keep the download source unchanged" ; \
    fi

### update apt and install libs
RUN apt-get update &&\
    apt-get install -y vim libsm6 libxext6 libxrender-dev libgl1-mesa-glx git wget libssl-dev libopencv-dev libspdlog-dev --no-install-recommends &&\
    rm -rf /var/lib/apt/lists/*

RUN curl -fsSL -v -o ~/miniconda.sh -O  https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh  && \
    chmod +x ~/miniconda.sh && \
    ~/miniconda.sh -b -p /opt/conda && \
    rm ~/miniconda.sh && \
    /opt/conda/bin/conda install -y python=${PYTHON_VERSION} conda-build pyyaml numpy ipython cython typing typing_extensions mkl mkl-include ninja && \
    /opt/conda/bin/conda clean -ya

### pytorch
RUN /opt/conda/bin/conda install pytorch==${TORCH_VERSION} torchvision==${TORCHVISION_VERSION} cudatoolkit=${CUDA} -c pytorch
ENV PATH /opt/conda/bin:$PATH

RUN pip install opencv_python==4.6.0.66 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com

### install mmcv-full
RUN /opt/conda/bin/pip install mmcv-full==${MMCV_VERSION} -f https://download.openmmlab.com/mmcv/dist/cu${CUDA//./}/torch${TORCH_VERSION}/index.html

RUN pip install onnxruntime_gpu==1.11.1 -i  https://pypi.mirrors.ustc.edu.cn/simple

WORKDIR /root/workspace
### get onnxruntime
RUN wget https://ghproxy.com/https://github.com/microsoft/onnxruntime/releases/download/v${ONNXRUNTIME_VERSION}/onnxruntime-linux-x64-${ONNXRUNTIME_VERSION}.tgz \
    && tar -zxvf onnxruntime-linux-x64-${ONNXRUNTIME_VERSION}.tgz &&\
    pip install onnxruntime-gpu==${ONNXRUNTIME_VERSION}

### cp trt from pip to conda
RUN cp -r /usr/local/lib/python${PYTHON_VERSION}/dist-packages/tensorrt* /opt/conda/lib/python${PYTHON_VERSION}/site-packages/

RUN pip install h5py==3.7.0 -i  https://pypi.mirrors.ustc.edu.cn/simple
RUN pip install matplotlib==3.5.2 -i  https://pypi.mirrors.ustc.edu.cn/simple

### install mmdeploy
ENV ONNXRUNTIME_DIR=/root/workspace/onnxruntime-linux-x64-${ONNXRUNTIME_VERSION}
ENV TENSORRT_DIR=/workspace/tensorrt
ARG VERSION
RUN git clone https://gitee.com/open-mmlab/mmdeploy &&\
    cd mmdeploy &&\
    if [ -z ${VERSION} ] ; then echo "No MMDeploy version passed in, building on master" ; else git checkout tags/v${VERSION} -b tag_v${VERSION} ; fi &&\
    git submodule update --init --recursive &&\
    mkdir -p build &&\
    cd build &&\
    cmake -DMMDEPLOY_TARGET_BACKENDS="ort;trt" .. &&\
    make -j$(nproc) &&\
    cd .. &&\
    pip install -e .

### build sdk
RUN git config --global http.sslverify false && \
    git config --global https.sslverify false && \
    git clone https://gitee.com/OpenPPL/ppl.cv.git && \
    cd ppl.cv && \
    git checkout tags/v${PPLCV_VERSION} -b v${PPLCV_VERSION} &&\
    ./build.sh cuda

ENV BACKUP_LD_LIBRARY_PATH=$LD_LIBRARY_PATH
ENV LD_LIBRARY_PATH=/usr/local/cuda-${CUDA}/compat/lib.real/:$LD_LIBRARY_PATH

RUN cd /root/workspace/mmdeploy &&\
    rm -rf build/CM* build/cmake-install.cmake build/Makefile build/csrc &&\
    mkdir -p build && cd build &&\
    cmake .. \
        -DMMDEPLOY_BUILD_SDK=ON \
        -DCMAKE_CXX_COMPILER=g++ \
        -Dpplcv_DIR=/root/workspace/ppl.cv/cuda-build/install/lib/cmake/ppl \
        -DTENSORRT_DIR=${TENSORRT_DIR} \
        -DONNXRUNTIME_DIR=${ONNXRUNTIME_DIR} \
        -DMMDEPLOY_BUILD_SDK_PYTHON_API=ON \
        -DMMDEPLOY_TARGET_DEVICES="cuda;cpu" \
        -DMMDEPLOY_TARGET_BACKENDS="ort;trt" \
        -DMMDEPLOY_CODEBASES=all &&\
    make -j$(nproc) && make install &&\
    cd install/example  && mkdir -p build && cd build &&\
    cmake -DMMDeploy_DIR=/root/workspace/mmdeploy/build/install/lib/cmake/MMDeploy .. &&\
    make -j$(nproc) && export SPDLOG_LEVEL=warn &&\
    if [ -z ${VERSION} ] ; then echo "Built MMDeploy master for GPU devices successfully!" ; else echo "Built MMDeploy version v${VERSION} for GPU devices successfully!" ; fi

ENV LD_LIBRARY_PATH="/root/workspace/mmdeploy/build/lib:${BACKUP_LD_LIBRARY_PATH}"


RUN pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pycuda

# clone mmdetection, build mmdetection, download faster_rcnn_r50 pretrain model
RUN git clone https://gitee.com/open-mmlab/mmdetection.git && \
    cd mmdetection && \
    pip install -e . && \
    mkdir checkpoints && \
    cd checkpoints && \
    wget https://download.openmmlab.com/mmdetection/v2.0/faster_rcnn/faster_rcnn_r50_fpn_1x_coco/faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth && \
    mv faster_rcnn_r50_fpn_1x_coco_20200130-047c8118.pth faster_rcnn_r50_fpn_1x_coco.pth && \
    cd ../../

# clone mmclassifier, build mmclassifier, download mobilenetv2 pretrain model
RUN git clone https://gitee.com/open-mmlab/mmclassification.git && cd mmclassification && pip install -e . && mkdir checkpoints && cd checkpoints && wget https://download.openmmlab.com/mmclassification/v0/resnext/resnext50_32x4d_b32x8_imagenet_20210429-56066e27.pth -O resnext50_32x4d_b32x8_imagenet.pth
3️⃣ 编译mmdeploy的docker仓库

–build-arg USE_SRC_2104=true : 切换成阿里源安装依赖 (这个参数很重要啊,否则会报错)

nvidia-docker build -f Dockerfile.mmdeploy -t mmdeploy:2104 . --build-arg  USE_SRC_2104=true
4️⃣ 模型文件生成(不进入容器)
# create directory and download checkpoint into it
mkdir volume_share
wget https://download.openmmlab.com/mmdetection/v2.0/yolox/yolox_s_8x8_300e_coco/yolox_s_8x8_300e_coco_20211121_095711-4592a793.pth -O volume_share/checkpoint.pth

# run conversion command with checkpoint dir mounted
nvidia-docker run -it -v $(pwd)/volume_share:/volume_share mmdeploy:latest python /root/workspace/mmdeploy/tools/deploy.py \
    /root/workspace/mmdeploy/configs/mmdet/detection/detection_tensorrt-fp16_static-800x1344.py \
    /mmdetection/configs/yolox/yolox_s_8x8_300e_coco.py \
    /volume_share/checkpoint.pth \
    /mmdetection/demo/demo.jpg \
    --work-dir /volume_share \
    --show \
    --device cuda:0
5️⃣ 进入docker容器
docker run --gpus all -it -p 8080:8080 -v /home/xbsj/gaoying/mmdeploy_out/:/root/workspace/mmdeploy_out mmdeploy:2104

mmdeploy安装(docker安装)

官方安装文档: 使用 Docker 镜像 — mmdeploy 0.5.0 文档

mmdeploy docker中各软件包配置:

包名版本
tensorrt7.2.3.4
pytorch1.8.0 py3.8_cuda10.2_cudnn7.6.5_0
cuda11.3
python3.8.13
mmcv1.4.0
mmdeploy0.5.0
驱动版本driver470.129.06
gcc9.3.0
1️⃣ 克隆mmdeploy

我给的是镜像加速的mmdeploy git源,妈妈再也不用担心我git clone超时了。

git clone https://api.mtr.pub/open-mmlab/mmdeploy.git
2️⃣ 构建docker镜像

这一步需要等的时间有点长,并且还可能因为网络不好,会报错。

# 以 GPU 为例
cd mmdeploy
docker build docker/GPU/ -t mmdeploy:2104 --build-arg  USE_SRC_2104=true
3️⃣ 进入 docker 容器

构建 docker 镜像成功后,我们可以使用 docker run 启动 docker 服务。 根据上边创建时的命令命名最后的mmdeploy:2104 :

docker run --gpus all -it -p 8080:8080 -v /home/xbsj/gaoying/mmdeploy_out/:/root/workspace/mmdeploy_out mmdeploy:2104

⚠️ ps:如果报错找不到gpu命令,错误提示:Error response from daemon: could not select device driver “” with capabilities: [[gpu]]

这是由于在容器里使用gpu,需要安装 nvida container toolkit。

apt-get install nvidia-container-runtime

安装后重新启动docker

systemctl restart docker

⚠️ PS: 如果提醒你断言错误,那个模块找不到那个方法,可能就是mmcv版本的错误,重装一下mmcv的版本,用mmcv1.4.0。

pip install mmcv==1.4.0

⚠️ PS: 如果提醒你:ModuleNotFoundError: No module named ‘pycuda’,那就安装一下:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pycuda
  • 10
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

gy-7

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

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

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

打赏作者

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

抵扣说明:

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

余额充值