华为云用户手册

  • 镜像版本 本教程中用到基础镜像地址和配套版本关系如下表所示,请提前了解。 表1 基础容器镜像地址 镜像用途 镜像地址 配套版本 基础镜像 swr.cn-southwest-2.myhuaweicloud.com/atelier/pytorch_2_1_ascend:pytorch_2.1.0-cann_8.0.rc2-py_3.9-hce_2.0.2312-aarch64-snt9b-20240528150158-b521cc0 CANN:cann_8.0.rc2 PyTorch:2.1.0
  • Step9 构建推理代码 提前在E CS 中构建推理代码,用于后续在推理生产环境中部署推理服务。 执行GIT安装命令。 sudo yum update sudo yum install git 解压AscendCloud-3rdLLM-6.3.905-xxx.zip代码包。 unzip AscendCloud-3rdLLM-6.3.905-*.zip 运行推理构建脚本build.sh文件,自动获取ascend_vllm_adapter文件夹中提供的vLLM相关算子代码。 cd llm_inference bash build.sh 运行完后,在当前目录下会生成ascend_vllm文件夹,即为昇腾适配后的vLLM代码。 将生成的ascend_vllm文件夹从ECS中取出并上传至OBS中。
  • 模型软件包结构说明 本教程需要使用到的AscendCloud-3rdLLM-xxx.zip软件包中的关键文件介绍如下。 ├──llm_tools #推理工具包 ├──llm_evaluation #推理评测代码包 ├──benchmark_eval # 精度评测 ├── config ├── config.json # 请求的参数,根据实际启动的服务来调整 ├── mmlu_subject_mapping.json # 数据集配置 ├── ... ├── evaluators ├── evaluator.py # 数据集数据预处理方法集 ├── model.py # 发送请求的模块,在这里修改请求响应。目前支持vllm.openai,atb的tgi模板 ├── ... ├── eval_test.py # 启动脚本,建立线程池发送请求,并汇总结果 ├── service_predict.py # 发送请求的服务。支持vllm的openai,atb的tgi模板 ├── ... ├──benchmark_tools #性能评测 ├── benchmark.py # 可以基于默认的参数跑完静态benchmark和动态benchmark ├── benchmark_parallel.py # 评测静态性能脚本 ├── benchmark_serving.py # 评测动态性能脚本 ├── benchmark_utils.py # 抽离的工具集 ├── generate_datasets.py # 生成自定义数据集的脚本 ├── requirements.txt # 第三方依赖 ├── ... ├──llm_inference #推理代码 ├── ascend_vllm_adapter #昇腾vLLM使用的算子模块 ├── ascend.txt #基于开源vLLM适配过NPU的patch脚本 ├── autosmoothquant_ascend.txt #基于开源autosmoothquant适配过NPU的patch脚本 ├── build.sh #推理构建脚本 ├── requirements.txt # 第三方依赖
  • 获取配套版本 本方案支持的软件配套版本和依赖包获取地址如表1所示。 表1 软件配套版本和获取地址 软件名称 说明 下载地址 AscendCloud-3rdLLM-6.3.905-xxx.zip 说明: 软件包名称中的xxx表示时间戳。 包含了本教程中使用到的vLLM 0.3.2推理部署代码和推理评测代码。代码包具体说明请参见模型软件包结构说明。 获取路径:Support-E 说明: 如果没有下载权限,请联系您所在企业的华为方技术支持下载获取。 AscendCloud-OPP-6.3.905-xxx.zip 推理依赖的算子包。
  • 准备权重 获取对应模型的权重文件,获取链接参考表1。 在创建的OBS桶下创建文件夹用以存放权重文件,例如在桶中创建文件夹。将下载的权重文件上传至OBS中,得到OBS下数据集结构。此处以qwen-14b举例。 obs://${bucket_name}/${folder-name}/ #OBS桶名称和文件目录可以自定义创建,此处仅为举例。 ├── config.json ├── generation_config.json ├── gitattributes.txt ├── LICENSE.txt ├── Notice.txt ├── pytorch_model-00001-of-00003.bin ├── pytorch_model-00002-of-00003.bin ├── pytorch_model-00003-of-00003.bin ├── pytorch_model.bin.index.json ├── README.md ├── special_tokens_map.json ├── tokenizer_config.json ├── tokenizer.json ├── tokenizer.model └── USE_POLICY.md └── ... 父主题: 准备工作
  • 创建OBS桶 ModelArts使用 对象存储服务 (Object Storage Service,简称OBS)存储输入输出数据、运行代码和模型文件,实现安全、高可靠和低成本的存储需求。因此,在使用ModelArts之前通常先创建一个OBS桶,然后在OBS桶中创建文件夹用于存放数据。 本文档也以将运行代码存放OBS为例,请参考创建OBS桶,例如桶名:standard-qwen-14b。并在该桶下创建文件夹目录用于后续存储代码使用,例如:code。 创建的OBS桶和开通的Standard资源必须在同一个Region。
  • 操作流程 图1 操作流程图 表2 操作任务流程说明 阶段 任务 说明 准备工作 准备资源 本教程案例是基于ModelArts Standard运行,需要购买ModelArts专属资源池。 准备权重 准备对应模型的权重文件。 准备代码 准备AscendCloud-3rdLLM-6.3.905-xxx.zip和AscendCloud-OPP-6.3.905-xxx.zip。 准备镜像 准备推理模型适用的容器镜像。 准备Notebook 本案例在Notebook上部署推理服务进行调试,因此需要创建Notebook。 部署推理服务 在Notebook调试环境中部署推理服务 介绍如何在Notebook中配置NPU环境,部署并启动推理服务,完成精度测试和性能测试。 在推理生产环境中部署推理服务 介绍如何在创建AI应用,部署并启动推理服务,在线预测在线服务。
  • 支持的模型列表 本方案支持的模型列表、对应的开源权重获取地址如表1所示。 表1 支持的模型列表和权重获取地址 序号 支持模型 支持模型参数量 开源权重获取地址 1 Llama llama-7b https://huggingface.co/huggyllama/llama-7b 2 llama-13b https://huggingface.co/huggyllama/llama-13b 3 llama-65b https://huggingface.co/huggyllama/llama-65b 4 Llama2- llama2-7b https://huggingface.co/meta-llama/Llama-2-7b-chat-hf 5 llama2-13b https://huggingface.co/meta-llama/Llama-2-13b-chat-hf 6 llama2-70b https://huggingface.co/meta-llama/Llama-2-70b-hf https://huggingface.co/meta-llama/Llama-2-70b-chat-hf (推荐) 7 Llama3 llama3-8b https://huggingface.co/meta-llama/Meta-Llama-3-8B-Instruct 8 llama3-70b https://huggingface.co/meta-llama/Meta-Llama-3-70B-Instruct 9 Yi yi-6b https://huggingface.co/01-ai/Yi-6B-Chat 10 yi-9b https://huggingface.co/01-ai/Yi-9B 11 yi-34b https://huggingface.co/01-ai/Yi-34B-Chat 12 Deepseek deepseek-llm-7b https://huggingface.co/deepseek-ai/deepseek-llm-7b-chat 13 deepseek-coder-instruct-33b https://huggingface.co/deepseek-ai/deepseek-coder-33b-instruct 14 deepseek-llm-67b https://huggingface.co/deepseek-ai/deepseek-llm-67b-chat 15 Qwen qwen-7b https://huggingface.co/Qwen/Qwen-7B-Chat 16 qwen-14b https://huggingface.co/Qwen/Qwen-14B-Chat 17 qwen-72b https://huggingface.co/Qwen/Qwen-72B-Chat 18 Qwen1.5 qwen1.5-0.5b https://huggingface.co/Qwen/Qwen1.5-0.5B-Chat 19 qwen1.5-7b https://huggingface.co/Qwen/Qwen1.5-7B-Chat 20 qwen1.5-1.8b https://huggingface.co/Qwen/Qwen1.5-1.8B-Chat 21 qwen1.5-14b https://huggingface.co/Qwen/Qwen1.5-14B-Chat 22 qwen1.5-32b https://huggingface.co/Qwen/Qwen1.5-32B/tree/main 23 qwen1.5-72b https://huggingface.co/Qwen/Qwen1.5-72B-Chat 24 qwen1.5-110b https://huggingface.co/Qwen/Qwen1.5-110B-Chat 25 Baichuan baichuan2-7b https://huggingface.co/baichuan-inc/Baichuan2-7B-Chat 26 baichuan2-13b https://huggingface.co/baichuan-inc/Baichuan2-13B-Chat 27 ChatGLMv2 chatglm2-6b https://huggingface.co/THUDM/chatglm2-6b 28 chatglm3-6b https://huggingface.co/THUDM/chatglm3-6b 29 Gemma gemma-2b https://huggingface.co/google/gemma-2b 30 gemma-7b https://huggingface.co/google/gemma-7b 31 Mistral mistral-7b https://huggingface.co/mistralai/Mistral-7B-v0.1
  • Step4 下载原始模型包 从HuggingFace官网下载moondream2模型包到本地,下载地址:https://huggingface.co/vikhyatk/moondream2/tree/2024-03-06。 在宿主机上创建一个空目录/home/temp,将下载的模型包存放在宿主机/home/temp/moondream2目录下,修改目录权限后,复制到容器中。 mkdir /home/temp #创建一个空目录,将下载的模型包存放在宿主机/home/temp/moondream2目录下 chmod -R 777 moondream2 #修改moondream2目录权限 docker cp moondream2 moondream2:/home/ma-user/ #复制moondream2目录到容器中
  • Step3 启动容器镜像 启动容器镜像。启动前请先按照参数说明修改${}中的参数。 docker run -itd \ --device=/dev/davinci1 \ --device=/dev/davinci_manager \ --device=/dev/devmm_svm \ --device=/dev/hisi_hdc \ -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \ -v /usr/local/dcmi:/usr/local/dcmi \ -v /etc/ascend_install.info:/etc/ascend_install.info \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \ --shm-size 32g \ --net=bridge \ -v ${work_dir}:${container_work_dir} \ --name ${container_name} \ ${image_name} bash 参数说明: -v ${work_dir}:${container_work_dir}:代表需要在容器中挂载宿主机的目录。宿主机和容器使用不同的文件系统。work_dir为宿主机中工作目录,目录下存放着训练所需代码、数据等文件。container_work_dir为要挂载到的容器中的目录。为方便两个地址可以相同。 容器不能挂载到/home/ma-user目录,此目录为ma-user用户家目录。如果容器挂载到/home/ma-user下,拉起容器时会与基础镜像冲突,导致基础镜像不可用。 driver及npu-smi需同时挂载至容器。 --name ${container_name}:容器名称,进入容器时会用到,此处可以自己定义一个容器名称。 ${image_name}:容器镜像的名称。 通过容器名称进入容器中。 docker exec -it ${container_name} bash
  • Step1 准备环境 请参考DevServer资源开通,购买DevServer资源,并确保机器已开通,密码已获取,能通过SSH登录,不同机器之间网络互通。 当容器需要提供服务给多个用户,或者多个用户共享使用该容器时,应限制容器访问Openstack的管理地址(169.254.169.254),以防止容器获取宿主机的元数据。具体操作请参见禁止容器获取宿主机元数据。 检查环境。 SSH登录机器后,检查NPU设备检查。运行如下命令,返回NPU设备信息。 npu-smi info # 在每个实例节点上运行此命令可以看到NPU卡状态 npu-smi info -l | grep Total # 在每个实例节点上运行此命令可以看到总卡数 如出现错误,可能是机器上的NPU设备没有正常安装,或者NPU镜像被其他容器挂载。请先正常安装固件和驱动,或释放被挂载的NPU。 检查docker是否安装。 docker -v #检查docker是否安装 如尚未安装,运行以下命令安装docker。 yum install -y docker-engine.aarch64 docker-engine-selinux.noarch docker-runc.aarch64 配置IP转发,用于容器内的网络访问。执行以下命令查看net.ipv4.ip_forward配置项的值,如果为1,可跳过此步骤。 sysctl -p | grep net.ipv4.ip_forward 如果net.ipv4.ip_forward配置项的值不为1,执行以下命令配置IP转发。 sed -i 's/net\.ipv4\.ip_forward=0/net\.ipv4\.ip_forward=1/g' /etc/sysctl.conf sysctl -p | grep net.ipv4.ip_forward
  • Step8 精度评估 关闭数据集shuffle,保证训练数据一致。 修改/home/ma-user/open_clip/src/training/data.py文件,搜索get_wds_dataset函数,将两处shuffle关闭,修改代码如下。 if is_train: if not resampled: print("dataset unshuffled.") #pipeline.extend([ # detshuffle2( # bufsize=_SHARD_SHUFFLE_SIZE, # initial=_SHARD_SHUFFLE_INITIAL, # seed=args.seed, # epoch=shared_epoch, # ), # wds.split_by_node, # wds.split_by_worker, #]) print("wds unshuffled.") pipeline.extend([ # at this point, we have an iterator over the shards assigned to each worker at each node tarfile_to_samples_nothrow, # wds.tarfile_to_samples(handler=log_and_continue), # wds.shuffle( # bufsize=_SAMPLE_SHUFFLE_SIZE, # initial=_SAMPLE_SHUFFLE_INITIAL, # ), ]) 重新训练1个epoch。脚本参考内容如下。 cd /home/ma-user/open_clip python -m training.main \ --save-frequency 1 \ --zeroshot-frequency 1 \ --report-to tensorboard \ --train-data '/home/ma-user/open_clip/mscoco/{00000..00059}.tar' \ --train-num-samples 102400 \ --dataset-type webdataset \ --warmup 10000 \ --batch-size=256 \ --lr=1e-3 \ --wd=0.1 \ --epochs=1 \ --workers=8 \ --model ViT-B-32 训练完成后,tensorboard统计的记录会保存在/home/ma-user/open_clip/logs/xxx-model_ViT-B-32-lr_0.001-b_32-j_8-p_amp/tensorboard目录下。 通过docker cp命令将容器内tensorboard子目录复制到宿主机 /home下。 在宿主机上安装tensorboard并启动。 pip install tensorboard #安装 tensorboard --logdir=/home/tensorboard --bind_all #启动 启动成功后如下图所示。 图2 启动tensorboard 在浏览器访问http://{宿主机ip}:6006/。将train/loss导出为json,和GPU训练下导出的文件比较。
  • Step1 准备环境 请参考DevServer资源开通,购买DevServer资源,并确保机器已开通,密码已获取,能通过SSH登录,不同机器之间网络互通。 当容器需要提供服务给多个用户,或者多个用户共享使用该容器时,应限制容器访问Openstack的管理地址(169.254.169.254),以防止容器获取宿主机的元数据。具体操作请参见禁止容器获取宿主机元数据。 检查环境。 SSH登录机器后,检查NPU设备检查。运行如下命令,返回NPU设备信息。 npu-smi info # 在每个实例节点上运行此命令可以看到NPU卡状态 npu-smi info -l | grep Total # 在每个实例节点上运行此命令可以看到总卡数 如出现错误,可能是机器上的NPU设备没有正常安装,或者NPU镜像被其他容器挂载。请先正常安装固件和驱动,或释放被挂载的NPU。 检查docker是否安装。 docker -v #检查docker是否安装 如尚未安装,运行以下命令安装docker。 yum install -y docker-engine.aarch64 docker-engine-selinux.noarch docker-runc.aarch64 配置IP转发,用于容器内的网络访问。执行以下命令查看net.ipv4.ip_forward配置项的值,如果为1,可跳过此步骤。 sysctl -p | grep net.ipv4.ip_forward 如果net.ipv4.ip_forward配置项的值不为1,执行以下命令配置IP转发。 sed -i 's/net\.ipv4\.ip_forward=0/net\.ipv4\.ip_forward=1/g' /etc/sysctl.conf sysctl -p | grep net.ipv4.ip_forward
  • Step5 获取训练数据集 使用img2dataset工具下载数据集。首先需要在容器安装img2dataset,安装命令如下。 pip install img2dataset 参考官方指导下载开源mscoco数据集。 #下载metadata wget https://huggingface.co/datasets/ChristophSchuhmann/MS_COCO_2017_URL_TEXT/resolve/main/mscoco.parquet #使用img2dataset工具下载数据集 img2dataset --url_list mscoco.parquet --input_format "parquet"\ --url_col "URL" --caption_col "TEXT" --output_format webdataset\ --output_folder mscoco --processes_count 16 --thread_count 64 --image_size 256\ --enable_wandb True
  • Step3 启动容器 启动容器镜像。启动前请先按照参数说明修改${}中的参数。可以根据实际需要增加修改参数。 docker run -itd \ --device=/dev/davinci0 \ --device=/dev/davinci_manager \ --device=/dev/devmm_svm \ --device=/dev/hisi_hdc \ -v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi \ -v /usr/local/dcmi:/usr/local/dcmi \ -v /etc/ascend_install.info:/etc/ascend_install.info \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ -v /etc/localtime:/etc/localtime \ -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \ --shm-size 32g \ --net=bridge \ -v ${work_dir}:${container_work_dir} \ --name ${container_name} \ ${image_name} bash 参数说明: --name ${container_name} 容器名称,进入容器时会用到,此处可以自己定义一个容器名称。 -v ${work_dir}:${container_work_dir} 代表需要在容器中挂载宿主机的目录。宿主机和容器使用不同的文件系统。work_dir为宿主机中工作目录,目录下存放着训练所需代码、数据等文件。container_work_dir为要挂载到的容器中的目录。为方便两个地址可以相同。 容器不能挂载到/home/ma-user目录,此目录为ma-user用户家目录。如果容器挂载到/home/ma-user下,拉起容器时会与基础镜像冲突,导致基础镜像不可用。 driver及npu-smi需同时挂载至容器。 ${image_name} 代表镜像地址。 通过容器名称进入容器中。使用默认用户ma-user启动容器。 docker exec -it ${container_name} bash
  • Step4 下载并安装Open-clip源码包 从官网下载Open-clip源码包。 git clone https://github.com/mlfoundations/open_clip.git cd open_clip git reset --hard 37b2c6b321ee697df4c709ca95d6dc849fc7d214 37b2c6b321ee697df4c709ca95d6dc849fc7d214是commit号。 复制Open-clip源码包到容器/home/ma-user目录下。 docker cp open_clip open-clip:/home/ma-user/ 修改文件夹权限(注意:此处需要重新启动一个终端,使用root用户登录容器,修改文件夹权限,修改完后关闭这个终端。) docker exec -it --user root open-clip bash chown -R ma-user:ma-group open_clip exit 在步骤2打开的终端中,使用默认用户ma-user安装源码。 cd open_clip make install 在步骤2打开的终端中,使用默认用户ma-user安装依赖。 pip install -r requirements-training.txt pip install -r requirements-test.txt pip install tensorboard
  • Step6 训练Open clip模型 适配昇腾代码。 在目录/home/ma-user/open_clip/src/training下,修改main.py文件,在第10行添加如下代码。 import torch_npu from torch_npu.contrib import transfer_to_npu 同样,修改train.py文件,在第11行添加如上代码,如图1所示。 图1 修改train.py文件 单卡训练。 训练命令参考如下。 cd /home/ma-user/open_clip python -m training.main \ --save-frequency 1 \ --zeroshot-frequency 1 \ --report-to tensorboard \ --train-data '/home/ma-user/open_clip/mscoco/{00000..00059}.tar' \ --train-num-samples 102400 \ --dataset-type webdataset \ --warmup 10000 \ --batch-size=256 \ --lr=1e-3 \ --wd=0.1 \ --epochs=30 \ --workers=8 \ --model ViT-B-32 参数说明: save-frequency:指定运行多少个epoch就保存模型参数,可以调大。 report-to tensorboard:指定输出loss指标到tensorboard,一般需要做精度评估才需要带上。 train-num-samples:指定每个epoch需要训练的样本个数,不超过总样本个数。 batch-size:指定一次处理的数据batch。 epochs:指定训练的epoch个数。 训练结束后,模型输出目录为: /home/ma-user/open_clip/logs/xxx-model_ViT-B-32-lr_0.001-b_32-j_8-p_amp/checkpoints 多卡训练 训练命令参考如下。 cd /home/ma-user/open_clip/src torchrun --nproc_per_node 4 -m training.main \ --save-frequency 1 \ --zeroshot-frequency 1 \ --report-to tensorboard \ --train-data '/home/ma-user/open_clip/mscoco/{00000..00059}.tar' \ --train-num-samples 102400 \ --dataset-type webdataset \ --warmup 10000 \ --batch-size=256 \ --lr=1e-3 \ --wd=0.1 \ --epochs=30 \ --workers=8 \ --model ViT-B-32
  • Step7 推理验证 首先将上面训练的最终模型文件epoch_29.pt 复制到/home/ma-user/open_clip目录下,然后在/home/ma-user/open_clip下,执行如下命令。 vi inference.py 将下面的代码复制进去后保存。 import os import torch from PIL import Image import open_clip if 'DEVICE_ID' in os.environ: print("DEVICE_ID:", os.environ['DEVICE_ID']) else: os.environ['DEVICE_ID'] = "0" model, _, preprocess = open_clip.create_model_and_transforms('ViT-B-32', pretrained='/home/ma-user/open_clip/epoch_29.pt') model = model.to("npu") tokenizer = open_clip.get_tokenizer('ViT-B-32') image = preprocess(Image.open("./docs/CLIP.png")).unsqueeze(0) text = tokenizer(["a diagram", "a dog", "a cat"]) print("input image shape:", image.shape) print("input text shape:", text.shape) with torch.no_grad(), torch.cuda.amp.autocast(): image = image.to("npu") text = text.to("npu") image_features = model.encode_image(image) text_features = model.encode_text(text) print("output image shape:", image_features.shape) print("output text shape:", text_features.shape) image_features /= image_features.norm(dim=-1, keepdim=True) text_features /= text_features.norm(dim=-1, keepdim=True) text_probs = (100.0 * image_features @ text_features.T).softmax(dim=-1) print("Label probs:", text_probs) # prints: [[1., 0., 0.]] 运行推理脚本。 python inference.py 由于./docs/CLIP.png图片是一张图表,因此结果值和第一个文本"a diagram"吻合,结果值会接近[[1., 0., 0.]]。
  • 附录:大模型推理常见问题 问题1:在推理预测过程中遇到NPU out of memory 解决方法:调整推理服务启动时的显存利用率,将--gpu-memory-utilization的值调小。 问题2:在推理预测过程中遇到ValueError:User-specified max_model_len is greater than the drived max_model_len 解决方法: 修改config.json文件中的"seq_length"的值,"seq_length"需要大于等于 --max-model-len的值。 config.json存在模型对应的路径下,例如:/data/nfs/benchmark/tokenizer/chatglm3-6b/config.json 父主题: 主流开源大模型基于DevServer适配PyTorch NPU推理指导(6.3.905)
  • Step1 配置精度测试环境 获取精度测试代码。精度测试代码存放在代码包AscendCloud-3rdLLM-xxx.zip的llm_tools/llm_evaluation(6.3.905版本)目录中。代码目录结构如下。精度测试使用到的mmlu和ceval数据集已经提前打包在代码中。 benchmark_eval ├──apig_sdk # ma校验包 ├──cpu_npu # 检测资源消耗 ├── config │ ├── config.json # 服务的配置模板,已配置了ma-standard,tgi示例 │ ├── mmlu_subject_mapping.json # mmlu数据集学科信息 │ ├── ceval_subject_mapping.json # ceval数据集学科信息 ├── evaluators │ ├── evaluator.py # 数据集数据预处理方法集 │ ├── chatglm.py # 处理请求相应模块, 一般和chatglm的官方评测数据集ceval搭配 │ ├── llama.py # 处理请求相应模块, 一般和llama的评测数据集mmlu搭配 ├── mmlu-exam, mmlu数据集 ├── ceval-exam, ceval数据集 ├── eval_test.py # 启动脚本,建立线程池发送请求,并汇总结果 ├── readme.md # 说明文档 ├── requirements.txt # 第三方依赖 ├── service_predict.py # 发送请求的服务 上传精度测试代码到推理容器中。如果在Step5 进入容器安装推理依赖软件步骤中已经上传过AscendCloud-3rdLLM-x.x.x.zip并解压,无需重复执行。 进入benchmark_eval目录下,执行如下命令安装性能测试的关依赖。 pip install -r requirements.txt 执行精度测试启动脚本eval_test.py,具体操作命令如下,可以根据参数说明修改参数。 python eval_test.py \ --max_workers=1 \ --service_name=llama2-13b-chat-test \ --eval_dataset=ceval \ --service_url=http://${docker_ip}:8080/v1/completions \ --few_shot=3 \ --is_devserver=True \ --model_name=llama2 \ --deploy_method=vllm \ --vllm_model=${model_path} 参数说明: max_workers:请求的最大线程数,默认为1。 service_name:服务名称,保存评测结果时创建目录,示例为:llama2-13b-chat-test。 eval_dataset:评测使用的评测集(枚举值),目前仅支持mmlu、ceval。 service_url:成功部署推理服务后的服务预测地址,示例:http://${docker_ip}:8080/generate。此处的${docker_ip}替换为宿主机实际的IP地址,端口号8080来自前面配置的服务端口。 few_shot:开启少量样本测试后添加示例样本的个数。默认为3,取值范围为0~5整数。 is_devserver: 是否DevServer部署方式,True表示DevServer模式。False表示ModelArts Standard模式。 model_name:评测模型名称,llama2。 deploy_method:部署方法,不同的部署方式api参数输入、输出解析方式不同,目前支持tgi、ma_standard、vllm等方式。 vllm_model:deploy_method为vllm时,服务以openai的方式启动,vllm_model为启动服务时传入的model_path。
  • Step2 查看精度测试结果 默认情况下,评测结果会按照result/{service_name}/{eval_dataset}-{timestamp} 的目录结果保存到对应的测试工程。执行多少次,则会在{service_name}下生成多少次结果。 单独的评测结果如下: {eval_dataset}-{timestamp} # 例如: mmlu-20240205093257 ├── accuracy │ ├── evaluation_accuracy.xlsx # 测试的评分结果,包含各个学科数据集的评分和总和评分。 ├── infer_info │ ├── xxx1.csv # 单个数据集的评测结果 │ ├── ...... │ ├── xxxn.csv # 单个数据集的评测结果 ├── summary_result │ ├── answer_correct.xlsx # 回答正确的结果 │ ├── answer_error.xlsx # 保存回答了问题的选项,但是回答结果错误 │ ├── answer_result_unknow.xlsx # 保存未推理出结果的问题,例如超时、系统错误 │ ├── system_error.xlsx # 保存推理结果,但是可能答非所问,无法判断是否正确,需要人工判断进行纠偏。
  • 静态benchmark验证 本章节介绍如何进行静态benchmark验证。 已经上传benchmark验证脚本到推理容器中。如果在Step5 进入容器安装推理依赖软件步骤中已经上传过AscendCloud-3rdLLM-x.x.x.zip并解压,无需重复执行。 进入benchmark_tools目录下,执行如下命令安装性能测试的关依赖。 pip install -r requirements.txt 运行静态benchmark验证脚本benchmark_parallel.py,具体操作命令如下,可以根据参数说明修改参数。 cd benchmark_tools python benchmark_parallel.py --backend vllm --host ${docker_ip} --port 8080 --tokenizer /path/to/tokenizer --epochs 5 \ --parallel-num 1 4 8 16 32 --prompt-tokens 1024 2048 --output-tokens 128 256 --benchmark-csv benchmark_parallel.csv 参数说明 --backend:服务类型,支持tgi、vllm、mindspore、openai等。本文档使用的推理接口是vllm。 --host ${docker_ip}:服务部署的IP地址,${docker_ip}替换为宿主机实际的IP地址。 --port:推理服务端口8080。 --tokenizer:tokenizer路径,HuggingFace的权重路径。 --epochs:测试轮数,默认取值为5 --parallel-num:每轮并发数,支持多个,如 1 4 8 16 32。 --prompt-tokens:输入长度,支持多个,如 128 128 2048 2048,数量需和--output-tokens的数量对应。 --output-tokens:输出长度,支持多个,如 128 2048 128 2048,数量需和--prompt-tokens的数量对应。 --benchmark-csv:结果保存路径,如benchmark_parallel.csv。 脚本运行完成后,测试结果保存在benchmark_parallel.csv中,示例如下图所示。 图1 静态benchmark测试结果(示意图)
  • benchmark方法介绍 性能benchmark包括两部分。 静态性能测试:评估在固定输入、固定输出和固定并发下,模型的吞吐与首token延迟。该方式实现简单,能比较清楚的看出模型的性能和输入输出长度、以及并发的关系。 动态性能测试:评估在请求并发在一定范围内波动,且输入输出长度也在一定范围内变化时,模型的延迟和吞吐。该场景能模拟实际业务下动态的发送不同长度请求,能评估推理框架在实际业务中能支持的并发数。 性能benchmark验证使用到的脚本存放在代码包AscendCloud-3rdLLM-xxx.zip的llm_tools/llm_evaluation(6.3.905版本)目录中。 代码目录如下: benchmark_tools ├── benchmark_parallel.py # 评测静态性能脚本 ├── benchmark_serving.py # 评测动态性能脚本 ├── generate_dataset.py # 生成自定义数据集的脚本 ├── benchmark_utils.py # 工具函数集 ├── benchmark.py # 执行静态,动态性能评测脚本、 ├── requirements.txt # 第三方依赖
  • 动态benchmark 本章节介绍如何进行动态benchmark验证。 获取数据集。动态benchmark需要使用数据集进行测试,可以使用公开数据集,例如Alpaca、ShareGPT。也可以根据业务实际情况,使用generate_datasets.py脚本生成和业务数据分布接近的数据集。 方法一:使用公开数据集 ShareGPT下载地址: https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json Alpaca下载地址: https://github.com/tatsu-lab/stanford_alpaca/blob/main/alpaca_data.json 方法二:使用generate_dataset.py脚本生成数据集方法: generate_dataset.py脚本通过指定输入输出长度的均值和标准差,生成一定数量的正态分布的数据。具体操作命令如下,可以根据参数说明修改参数。 cd benchmark_tools python generate_dataset.py --dataset custom_datasets.json --tokenizer /path/to/tokenizer \ --min-input 100 --max-input 3600 --avg-input 1800 --std-input 500 \ --min-output 40 --max-output 256 --avg-output 160 --std-output 30 --num-requests 1000 generate_dataset.py脚本执行参数说明如下: --dataset:数据集保存路径,如custom_datasets.json --tokenizer:tokenizer路径,可以是HuggingFace的权重路径 --min-input:输入tokens最小长度,可以根据实际需求设置。 --max-input:输入tokens最大长度,可以根据实际需求设置。 --avg-input:输入tokens长度平均值,可以根据实际需求设置。 --std-input:输入tokens长度方差,可以根据实际需求设置。 --min-output:最小输出tokens长度,可以根据实际需求设置。 --max-output:最大输出tokens长度,可以根据实际需求设置。 --avg-output:输出tokens长度平均值,可以根据实际需求设置。 --std-output:输出tokens长度标准差,可以根据实际需求设置。 --num-requests:输出数据集的数量,可以根据实际需求设置。 执行脚本benchmark_serving.py测试动态benchmark。具体操作命令如下,可以根据参数说明修改参数。 cd benchmark_tools python benchmark_serving.py --backend vllm --host${docker_ip} --port 8085 --dataset custom_datasets.json --dataset-type custom \ --tokenizer /path/to/tokenizer --request-rate 0.01 1 2 4 8 10 20 --num-prompts 10 1000 1000 1000 1000 1000 1000 \ --max-tokens 4096 --max-prompt-tokens 3768 --benchmark-csv benchmark_serving.csv --backend:服务类型,如"tgi",vllm","mindspore" --host ${docker_ip}:服务部署的IP地址,${docker_ip}替换为宿主机实际的IP地址。 --port:服务端口 --dataset:数据集路径 --dataset-type:支持三种 "alpaca","sharegpt","custom"。custom为自定义数据集。 --tokenizer:tokenizer路径,可以是huggingface的权重路径 --request-rate:请求频率,支持多个,如 0.1 1 2。实际测试时,会根据request-rate为均值的指数分布来发送请求以模拟真实业务场景。 --num-prompts:某个频率下请求数,支持多个,如 10 100 100,数量需和--request-rate的数量对应 --max-tokens:输入+输出限制的最大长度,模型启动参数--max-input-length值需要大于该值 --max-prompt-tokens:输入限制的最大长度,推理时最大输入tokens数量,模型启动参数--max-total-tokens值需要大于该值,tokenizer建议带tokenizer.json的FastTokenizer --benchmark-csv:结果保存路径,如benchmark_serving.csv 脚本运行完后,测试结果保存在benchmark_serving.csv中,示例如下图所示。 图2 动态benchmark测试结果(示意图)
  • Step6 启动推理服务 配置需要使用的NPU卡编号。例如:实际使用的是第1张卡,此处填写“0”。 export ASCEND_RT_VISIBLE_DEVI CES =0 如果启动服务需要使用多张卡,例如:实际使用的是第1张和第2张卡,此处填写为“0,1”,以此类推。 export ASCEND_RT_VISIBLE_DEVICES=0,1 NPU卡编号可以通过命令npu-smi info查询。 配置PYTHONPATH。 export PYTHONPATH=$PYTHONPATH:${vllm_path} ${vllm_path} 填写ascend_vllm文件夹绝对路径。 高阶配置(可选)。 词表切分。 在分布式场景下,默认不使用词表切分能提升推理性能,同时也会增加单卡的显存占用。不建议开启词表并行,如确需使用词表切分,配置以下环境变量: export USE_VOCAB_PARALLEL=1 #打开词表切分开关 unset USE_VOCAB_PARALLEL #关闭词表切分开关 配置后重启服务生效。 Matmul_all_reduce融合算子。 使用Matmul_all_reduce融合算子能提升全量推理性能;该算子要求驱动和固件版本为Ascend HDK 24.1.RC1.B011及以上,默认不开启。如需开启,配置以下环境变量: export USE_MM_ALL_REDUCE_OP=1 #打开Matmul_all_reduce融合算子 unset USE_MM_ALL_REDUCE_OP #关闭Matmul_all_reduce融合算子 配置后重启服务生效。 查看详细日志。 查看详细耗时日志可以辅助定位性能瓶颈,但会影响推理性能。如需开启,配置以下环境变量: export DETAIL_TIME_ LOG =1 #打开打印详细日志 export RAY_DEDUP_LOGS=0 #打开打印详细日志 unset DETAIL_TIME_LOG #关闭打印详细日志 配置后重启服务生效。 启动服务与请求。此处提供vLLM服务API接口启动和OpenAI服务API接口启动2种方式。详细启动服务与请求方式参考:https://docs.vllm.ai/en/latest/getting_started/quickstart.html。 以下服务启动介绍的是在线推理方式,离线推理请参见https://docs.vllm.ai/en/latest/getting_started/quickstart.html#offline-batched-inference。 通过vLLM服务API接口启动服务 在ascend_vllm目录下通过vLLM服务API接口启动服务,具体操作命令如下,API Server的命令相关参数说明如下,可以根据参数说明修改配置。 python -m vllm.entrypoints.api_server --model ${container_model_path} \ --max-num-seqs=256 \ --max-model-len=4096 \ --max-num-batched-tokens=4096 \ --dtype=float16 \ --tensor-parallel-size=1 \ --block-size=128 \ --host=${docker_ip} \ --port=8080 \ --gpu-memory-utilization=0.9 \ --trust-remote-code 通过OpenAI服务API接口启动服务 在ascend_vllm目录下通OpenAI服务API接口启动服务,具体操作命令如下,可以根据参数说明修改配置。 python -m vllm.entrypoints.openai.api_server --model ${container_model_path} \ --max-num-seqs=256 \ --max-model-len=4096 \ --max-num-batched-tokens=4096 \ --dtype=float16 \ --tensor-parallel-size=1 \ --block-size=128 \ --host=${docker_ip} \ --port=8080 \ --gpu-memory-utilization=0.9 \ --trust-remote-code 具体参数说明如下: --model ${container_model_path}:模型地址,模型格式是HuggingFace的目录格式。即Step3 上传代码包和权重文件上传的HuggingFace权重文件存放目录。如果使用的是训练后模型转换为HuggingFace格式的地址,还需要有Tokenizer原始文件。 --max-num-seqs:最大同时处理的请求数,超过后拒绝访问。 --max-model-len:推理时最大输入+最大输出tokens数量,输入超过该数量会直接返回。max-model-len的值必须小于config.json文件中的"seq_length"的值,否则推理预测会报错。config.json存在模型对应的路径下,例如:${container_work_dir}/chatglm3-6b/config.json。不同模型推理支持的max-model-len长度不同,具体差异请参见附录:基于vLLM(v0.3.2)不同模型推理支持的max-model-len长度说明。 --max-num-batched-tokens:prefill阶段,最多会使用多少token,必须大于或等于--max-model-len,推荐使用4096或8192。 --dtype:模型推理的数据类型。支持FP16和BF16数据类型推理。float16表示FP16,bfloat16表示BF16。 --tensor-parallel-size:模型并行数。取值需要和启动的NPU卡数保持一致,可以参考1。此处举例为1,表示使用单卡启动服务。 --block-size:PagedAttention的block大小,推荐设置为128。 --host=${docker_ip}:服务部署的IP,${docker_ip}替换为宿主机实际的IP地址。 --port:服务部署的端口。 --gpu-memory-utilization:NPU使用的显存比例,复用原vLLM的入参名称,默认为0.9。 --trust-remote-code:是否相信远程代码。 服务启动后,会打印如下类似信息。 server launch time cost: 15.443044185638428 s INFO: Started server process [2878]INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit)
  • 附录:基于vLLM(v0.3.2)不同模型推理支持的max-model-len长度说明 基于vLLM(v0.3.2)部署推理服务时,不同模型推理支持的max-model-len长度说明如下面的表格所示。如需达到以下值,需要将--gpu-memory-utilization设为0.9,qwen系列、qwen1.5系列、llama3系列模型还需打开词表切分配置export USE_VOCAB_PARALLEL=1。 序号 模型名称 4*64GB 8*32GB 1 qwen1.5-72b 24576 8192 2 qwen-72b 24576 8192 3 llama3-70b 32768 8192 4 llama2-70b 98304 32768 6 llama-65b 24576 8192 序号 模型名称 2*64GB 4*32GB 1 qwen1.5-32b 65536 24576 序号 模型名称 1*64GB 1*32GB 1 qwen1.5-7b 49152 16384 2 qwen-7b 49152 16384 3 llama3-8b 98304 32768 4 llama2-7b 126976 16384 5 chatglm3-6b 126976 65536 6 chatglm2-6b 126976 65536 序号 模型名称 1*64GB 2*32GB 1 qwen1.5-14b 24576 24576 2 qwen-14b 24576 24576 3 llama2-13b 24576 24576 说明:机器型号规格以卡数*显存大小为单位,如4*64GB代表4张64GB显存的NPU卡。
  • Step1 检查环境 SSH登录机器后,检查NPU设备检查。运行如下命令,返回NPU设备信息。 npu-smi info # 在每个实例节点上运行此命令可以看到NPU卡状态 npu-smi info -l | grep Total # 在每个实例节点上运行此命令可以看到总卡数 如出现错误,可能是机器上的NPU设备没有正常安装,或者NPU镜像被其他容器挂载。请先正常安装固件和驱动,或释放被挂载的NPU。 检查docker是否安装。 docker -v #检查docker是否安装 如尚未安装,运行以下命令安装docker。 yum install -y docker-engine.aarch64 docker-engine-selinux.noarch docker-runc.aarch64 配置IP转发,用于容器内的网络访问。执行以下命令查看net.ipv4.ip_forward配置项的值,如果为1,可跳过此步骤。 sysctl -p | grep net.ipv4.ip_forward 如果net.ipv4.ip_forward配置项的值不为1,执行以下命令配置IP转发。 sed -i 's/net\.ipv4\.ip_forward=0/net\.ipv4\.ip_forward=1/g' /etc/sysctl.conf sysctl -p | grep net.ipv4.ip_forward
  • Step5 进入容器安装推理依赖软件 通过容器名称进入容器中。默认使用ma-user用户执行后续命令。 docker exec -it ${container_name} bash 上传代码和权重到宿主机时使用的是root用户,此处需要执行如下命令统一文件属主为ma-user用户。 #统一文件属主为ma-user用户 sudo chown -R ma-user:ma-group ${container_work_dir} # ${container_work_dir}:/home/ma-user/ws 容器内挂载的目录 #例如:sudo chown -R ma-user:ma-group /home/ma-user/ws 解压算子包并将相应算子安装到环境中。 unzip AscendCloud-OPP-*.zip pip install ascend_cloud_ops-1.0.0-py3-none-any.whl pip install cann_ops-1.0.0-py3-none-any.whl 解压软件推理代码并安装依赖包。 unzip AscendCloud-3rdLLM-*.zip cd llm_inference pip install -r requirements.txt 运行推理构建脚本build.sh文件,会自动获取ascend_vllm_adapter文件夹中提供的vLLM相关算子代码。 cd llm_inference bash build.sh 运行完后,在当前目录下会生成ascend_vllm文件夹,即为昇腾适配后的vLLM代码。
  • Step4 启动容器镜像 启动容器镜像前请先按照参数说明修改${}中的参数。 docker run -itd \ --device=/dev/davinci0 \ --device=/dev/davinci1 \ --device=/dev/davinci2 \ --device=/dev/davinci3 \ --device=/dev/davinci4 \ --device=/dev/davinci5 \ --device=/dev/davinci6 \ --device=/dev/davinci7 \ -v /etc/localtime:/etc/localtime \ -v /usr/local/Ascend/driver:/usr/local/Ascend/driver \ -v /etc/ascend_install.info:/etc/ascend_install.info \ --device=/dev/davinci_manager \ --device=/dev/devmm_svm \ --device=/dev/hisi_hdc \ -v /var/log/npu/:/usr/slog \ -v /usr/local/sbin/npu-smi:/usr/local/sbin/npu-smi \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ -v ${dir}:${container_work_dir} \ --net=host \ --name ${container_name} \ ${image_id} \ /bin/bash 参数说明: --device=/dev/davinci0,..., --device=/dev/davinci7:挂载NPU设备,示例中挂载了8张卡davinci0~davinci7。 -v ${dir}:${container_work_dir} 代表需要在容器中挂载宿主机的目录。宿主机和容器使用不同的大文件系统,dir为宿主机中文件目录,${container_work_dir}为要挂载到的容器中的目录。为方便两个地址可以相同。 容器不能挂载到/home/ma-user目录,此目录为ma-user用户家目录。如果容器挂载到/home/ma-user下,拉起容器时会与基础镜像冲突,导致基础镜像不可用。 driver及npu-smi需同时挂载至容器。 不要将多个容器绑到同一个NPU上,会导致后续的容器无法正常使用NPU功能。 --name ${container_name}:容器名称,进入容器时会用到,此处可以自己定义一个容器名称。 {image_id} 为docker镜像的ID,在宿主机上可通过docker images查询得到。
  • 模型软件包结构说明 本教程需要使用到的AscendCloud-3rdLLM-xxx.zip软件包中的关键文件介绍如下。 ├──llm_tools #推理工具包 ├──llm_evaluation #推理评测代码包 ├──benchmark_eval # 精度评测 ├── config ├── config.json # 请求的参数,根据实际启动的服务来调整 ├── mmlu_subject_mapping.json # 数据集配置 ├── ... ├── evaluators ├── evaluator.py # 数据集数据预处理方法集 ├── model.py # 发送请求的模块,在这里修改请求响应。目前支持vllm.openai,atb的tgi模板 ├── ... ├── eval_test.py # 启动脚本,建立线程池发送请求,并汇总结果 ├── service_predict.py # 发送请求的服务。支持vllm的openai,atb的tgi模板 ├── ... ├──benchmark_tools #性能评测 ├── benchmark.py # 可以基于默认的参数跑完静态benchmark和动态benchmark ├── benchmark_parallel.py # 评测静态性能脚本 ├── benchmark_serving.py # 评测动态性能脚本 ├── benchmark_utils.py # 抽离的工具集 ├── generate_datasets.py # 生成自定义数据集的脚本 ├── requirements.txt # 第三方依赖 ├── ... ├──llm_inference #推理代码 ├── ascend_vllm_adapter #昇腾vLLM使用的算子模块 ├── ascend.txt #基于开源vLLM适配过NPU的patch脚本 ├── autosmoothquant_ascend.txt #基于开源autosmoothquant适配过NPU的patch脚本 ├── build.sh #推理构建脚本 ├── requirements.txt # 第三方依赖
共100000条