当前位置: 首页 > news >正文

华为昇腾 910B 部署 DeepSeek-R1 蒸馏系列模型详细指南

本文记录 在 华为昇腾 910B(65GB) * 8 上 部署 DeepSeekR1 蒸馏系列模型(14B、32B)全过程与测试结果。

NPU:910B3 (65GB) * 8 (910B 有三个版本 910B1、2、3)

模型:DeepSeek-R1-Distill-Qwen-14B、DeepSeek-R1-Distill-Qwen-32B

部署方法:镜像部署 1.0.0-800I-A2-py311-openeuler24.03-lts  (需要申请下载权限,审核需要2天左右)

本文基础环境如下:

----------------
aarch64
910B(65GB) * 8
CANN 7.0
npu-smi 23.0.2.1
----------------

模型下载

DeepSeek-R1-Distill-Qwen-14B · 模型库

DeepSeek-R1-Distill-Qwen-32B · 模型库

modelscope 魔搭社区模型下载

本文将模型下载到服务器的 /data1/apps/models​ 路径下

  • 例如 /data1/apps/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B​

启动镜像时,将路径挂载:-v /data1/apps/models:/storage/llm​

那么在镜像容器内模型地址:

​/storage/llm/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B​

权重转换

14B、32B 是.safetensor权重,无需转换,可以直接使用。

环境依赖

拉取镜像

下载地址: 昇腾镜像仓库详情

登陆账号,申请下载权限 -- 点击立即下载 --- 弹出一个窗口 -- 按照指示拉取镜像

docker pull  --platform=linux/arm64  swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:1.0.0-800I-A2-py311-openeuler24.03-lts

--platform=linux/arm64 指定拉去内核为 arm 架构版本的镜像

由于本文的910B是纯内网机器,无法直接访问下载

于是 找了台可以访问公网的机器(x86的),拉取镜像、导出、传输到内网机器、导入

如果你的机器可以访问公网,直接拉去即可

查看拉取的镜像版本

docker inspect 25ba5f455ae3| grep Architecture

导出镜像

docker save -o 1.0.0-800I-A2-py311-openeuler24.03-lts.tar swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:1.0.0-800I-A2-py311-openeuler24.03-lts
  • 加载
docker load -i 1.0.0-800I-A2-py311-openeuler24.03-lts.tar1.0.0-300I-Duo-py311-openeuler24.03-lts.tar
  • 环境

    • python 3.11
    • torch 2.1
    [root@pm-a813-005 DeepSeek-R1-Distill-Qwen-14B]# python --version
    Python 3.11.6
    [root@pm-a813-005 DeepSeek-R1-Distill-Qwen-14B]# pip show torch
    Name: torch
    Version: 2.1.0
    Summary: Tensors and Dynamic neural networks in Python with strong GPU acceleration
    Home-page: https://pytorch.org/
    Author: PyTorch Team
    Author-email: packages@pytorch.org
    License: BSD-3
    Location: /usr/local/lib64/python3.11/site-packages
    Requires: filelock, fsspec, jinja2, networkx, sympy, typing-extensions
    Required-by: accelerate, torch-npu, torchvision
    • mindie_llm 1.0.0
    • mindiebenchmark 1.0.0
    • mindieclient 1.0.0
    • mindiesd 1.0.0
    • mindietorch 1.0.0+torch2.1.0.abi0

启动镜像

root 特权模型

docker run -it -d --net=host --shm-size=10g \--privileged \--name deepseek-r1-distill-root-test \-v /usr/local/Ascend/driver:/usr/local/Ascend/driver:ro \-v /usr/local/sbin:/usr/local/sbin:ro \-v /data1/apps/models:/storage/llm \swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:1.0.0-800I-A2-py311-openeuler24.03-lts \bash
docker exec -it deepseek-r1-distill-root-test bash

普通用户

docker run -it -d --net=host --shm-size=10g \--name deepseek-r1-distill-test1 \--device=/dev/davinci_manager \--device=/dev/hisi_hdc \--device=/dev/devmm_svm \--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 /usr/local/Ascend/driver:/usr/local/Ascend/driver:ro \-v /usr/local/sbin:/usr/local/sbin:ro \-v /data1/apps/models:/storage/llm \-w /storage/llm \swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:1.0.0-800I-A2-py311-openeuler24.03-lts \bash

注意,以上启动命令仅供参考,请根据需求自行修改再启动容器,尤其需要注意:

  1. ​--user​,如果您的环境中HDK是通过普通用户安装(例如默认的HwHiAiUser​,可以通过id HwHiAiUser​命令查看该用户组ID),请设置好对应的用户组,例如用户组1001可以使用HDK,则--user mindieuser:1001​,镜像中默认使用的是用户组1000。如果您的HDK是由root用户安装,且指定了--install-for-all​参数,则无需指定--user​参数。

  2. 设定容器名称--name​与镜像名称,例如mindie:1.0.0-800I-A2-py311-openeuler24.03-lts​。

  3. 如果不使用--priviliged​参数,则需要设置各设备,包括设置想要使用的卡号--device​:

    ...
    --name <container-name> \
    --device=/dev/davinci_manager \
    --device=/dev/hisi_hdc \
    --device=/dev/davinci0 \
    ...
    
  4. 设定权重挂载的路径,-v /path-to-weights:/path-to-weights:ro​,注意,权重路径权限应当设置为750。如果使用普通用户镜像,权重路径所属应为镜像内默认的1000用户。可参考以下命令进行修改:

    chmod -R 755 /path-to-weights
    chown -R 1000:1000 /path-to-weights# 进入容器后执行
    chmod -R 755 /storage/llm
    chown -R 1000:1000 /storage/llm
    
  5. 在普通用户镜像中,注意所有文件均在 /home/mindieuser​ 下,请勿直接挂载 /home​ 目录,以免宿主机上存在相同目录,将容器内文件覆盖清除。

  • 进入容器
docker exec -it deepseek-r1-distill-test1 bash

确认环境

检验HDK是否可用

输入以下命令,应当正确显示设备信息:

npu-smi info

如果出现以下信息:

bash: npu-smi: command not found

说明宿主机上的 npu-smi​ 工具不在 /usr/local/sbin​ 路径中,可能是由于HDK版本过旧或其他原因导致,可以使用以下命令找到该工具,并在启动容器时将其挂载到容器内:

find / -name npu-smi

一般来说,可能出现在 /usr/local/bin/npu-smi​ 路径下。

检验Torch是否可用

启动Python,并输入以下命令:

import torch
import torch_npu

若无报错信息,则说明Torch组件正常。

检查MindIE各组件

输入以下命令:

pip list | grep mindie

应出现类似如下输出:

mindie_llm                        1.0.0
mindiebenchmark                   1.0.0
mindieclient                      1.0.0
mindiesd                          1.0.0
mindietorch                       1.0.0+torch2.1.0.abi0

或者输入以下命令:

cat /home/mindieuser/Ascend/mindie/latest/version.info

应出现类似如下输出:

Ascend-mindie : MindIE 1.0.0
mindie-rt: 1.0.0
mindie-torch: 1.0.0
mindie-service: 1.0.0
mindie-llm: 1.0.0
mindie-sd:1.0.0
Platform : aarch64

说明各组件正常。

确认模型地址正确

cd /storage/llm/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B
cd /storage/llm/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B
cd /storage/llm/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B

确认权限

chmod -R 750 /storage/llm

设置模型服务启动配置

打开配置文件

vi /usr/local/Ascend/mindie/latest/mindie-service/conf/config.json

修改建议

一般只需要修改以下配置(单实例)

{..."ServerConfig" :{..."port" : 1040, #自定义"managementPort" : 1041, #自定义"metricsPort" : 1042, #自定义..."httpsEnabled" : false,  # 取消https协议启动服务...},"BackendConfig": {..."npuDeviceIds" : [[0,1]],..."ModelDeployConfig":{"truncation" : false,"ModelConfig" : [{..."modelName" : "deepseek-14b","modelWeightPath" : "/storage/llm/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B","worldSize" : 2,...}]},}
}
  • (多实例)以 14B 为例, 一张卡一个实例, 八张就是八个实例,并发要求200
### ServerConfig
- **`httpsEnabled`**:取消https协议 设为 false### 3. `ModelDeployParam` 部分
#### 整体配置
- **`modelInstanceNumber`**:由于单卡能跑一个实例,机器有 8 张卡,可设置为 8。
- **`tokenizerProcessNumber`**:可使用默认值 8,也可根据实际性能情况进行调整。
- **`maxSeqLen`**:根据需求,最大上下文为 8192,设置为 8192 + 4096 = 12288(输入长度 + 输出长度)。
- **`npuDeviceIds`**:由于是单机 8 卡,设置为 `[[0], [1], [2], [3], [4], [5], [6], [7]]`。
- **`multiNodesInferEnabled`**:设置为 `false`,因为是单机推理。#### `ModelParam`
- **`worldSize`**:由于使用 8 张卡, 8 个实例,一个实例一张卡,设置为 1。
- **`cpuMemSize`**:CPU 内存有 1.4T,可适当增大,例如设置为 100(单位:GB)。
- **`npuMemSize`**:使用快速计算公式计算:- 假设单卡总空闲显存为 60GB,模型权重占用 40GB(根据实际情况调整),后处理占用 1GB,系数取 0.8。- 则 `npuMemSize = (60 - 40/1 - 1) * 0.8 ≈ 15`,可设置为 15(单位:GB)。### 4. `ScheduleParam` 部分
- **`maxPrefillBatchSize`**:可根据实际性能测试进行调整,初始可设置为 200。
- **`maxPrefillTokens`**:设置为大于等于 `maxSeqLen` 的值,例如设置为 16384。
- **`prefillTimeMsPerReq`**:可根据实际情况调整,使用默认值 150。
- **`prefillPolicyType`**:可使用默认值 0(FCFS,先来先服务)。
- **`decodeTimeMsPerReq`**:可根据实际情况调整,使用默认值 50。
- **`decodePolicyType`**:可使用默认值 0(FCFS,先来先服务)。
- **`maxBatchSize`**:根据 `npuMemSize` 和 `cacheBlockSize` 等参数重新计算,初始可设置为 200。
- **`maxIterTimes`**:最大输出为 4096,设置为 4096。
- **`maxPreemptCount`**:可根据实际情况设置,初始可设置为 0。
- **`supportSelectBatch`**:可根据实际情况设置,初始可使用默认值 `false`。
- **`maxQueueDelayMicroseconds`**:使用默认值 5000。### 预估最大并发量
最大并发量受多种因素影响,包括模型复杂度、硬件性能、参数配置等。
上面的配置,理论上最大并发量可达到 200 左右,但实际并发量需要通过性能测试来确定。可以逐步增加并发请求,观察系统的响应时间、资源利用率等指标,找到系统的性能瓶颈,从而确定最大并发量。

配置示例

14B
{"Version" : "1.1.0","LogConfig" :{"logLevel" : "Info","logFileSize" : 20,"logFileNum" : 20,"logPath" : "logs/mindservice.log"},"ServerConfig" :{"ipAddress" : "127.0.0.1","managementIpAddress" : "127.0.0.2","port" : 1025,"managementPort" : 1026,"metricsPort" : 1027,"allowAllZeroIpListening" : false,"maxLinkNum" : 1000,"httpsEnabled" : false,"fullTextEnabled" : false,"tlsCaPath" : "security/ca/","tlsCaFile" : ["ca.pem"],"tlsCert" : "security/certs/server.pem","tlsPk" : "security/keys/server.key.pem","tlsPkPwd" : "security/pass/key_pwd.txt","tlsCrlPath" : "security/certs/","tlsCrlFiles" : ["server_crl.pem"],"managementTlsCaFile" : ["management_ca.pem"],"managementTlsCert" : "security/certs/management/server.pem","managementTlsPk" : "security/keys/management/server.key.pem","managementTlsPkPwd" : "security/pass/management/key_pwd.txt","managementTlsCrlPath" : "security/management/certs/","managementTlsCrlFiles" : ["server_crl.pem"],"kmcKsfMaster" : "tools/pmt/master/ksfa","kmcKsfStandby" : "tools/pmt/standby/ksfb","inferMode" : "standard","interCommTLSEnabled" : true,"interCommPort" : 1121,"interCommTlsCaPath" : "security/grpc/ca/","interCommTlsCaFiles" : ["ca.pem"],"interCommTlsCert" : "security/grpc/certs/server.pem","interCommPk" : "security/grpc/keys/server.key.pem","interCommPkPwd" : "security/grpc/pass/key_pwd.txt","interCommTlsCrlPath" : "security/grpc/certs/","interCommTlsCrlFiles" : ["server_crl.pem"],"openAiSupport" : "vllm"},"BackendConfig" : {"backendName" : "mindieservice_llm_engine","modelInstanceNumber" : 8,"npuDeviceIds" : [[0], [1], [2], [3], [4], [5], [6], [7]],"tokenizerProcessNumber" : 8,"multiNodesInferEnabled" : false,"multiNodesInferPort" : 1120,"interNodeTLSEnabled" : true,"interNodeTlsCaPath" : "security/grpc/ca/","interNodeTlsCaFiles" : ["ca.pem"],"interNodeTlsCert" : "security/grpc/certs/server.pem","interNodeTlsPk" : "security/grpc/keys/server.key.pem","interNodeTlsPkPwd" : "security/grpc/pass/mindie_server_key_pwd.txt","interNodeTlsCrlPath" : "security/grpc/certs/","interNodeTlsCrlFiles" : ["server_crl.pem"],"interNodeKmcKsfMaster" : "tools/pmt/master/ksfa","interNodeKmcKsfStandby" : "tools/pmt/standby/ksfb","ModelDeployConfig" :{"maxSeqLen" : 12288,"maxInputTokenLen" : 8192,"truncation" : false,"ModelConfig" : [{"modelInstanceType" : "Standard","modelName" : "deepseek-14b","modelWeightPath" : "/storage/llm/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B","worldSize" : 1,"cpuMemSize" : 50,"npuMemSize" : -1,"backendType" : "atb","trustRemoteCode" : false}]},"ScheduleConfig" :{"templateType" : "Standard","templateName" : "Standard_LLM","cacheBlockSize" : 128,"maxPrefillBatchSize" : 200,"maxPrefillTokens" : 16384,"prefillTimeMsPerReq" : 150,"prefillPolicyType" : 0,"decodeTimeMsPerReq" : 50,"decodePolicyType" : 0,"maxBatchSize" : 200,"maxIterTimes" : 4096,"maxPreemptCount" : 0,"supportSelectBatch" : false,"maxQueueDelayMicroseconds" : 5000}}
}
32B
{"Version" : "1.1.0","LogConfig" :{"logLevel" : "Verbose","logFileSize" : 200,"logFileNum" : 64,"logPath" : "logs/mindservice.log"},"ServerConfig" :{"ipAddress" : "127.0.0.1","managementIpAddress" : "127.0.0.2","port" : 1025,"managementPort" : 1026,"metricsPort" : 1027,"allowAllZeroIpListening" : false,"maxLinkNum" : 1000,"httpsEnabled" : false,"fullTextEnabled" : false,"tlsCaPath" : "security/ca/","tlsCaFile" : ["ca.pem"],"tlsCert" : "security/certs/server.pem","tlsPk" : "security/keys/server.key.pem","tlsPkPwd" : "security/pass/key_pwd.txt","tlsCrlPath" : "security/certs/","tlsCrlFiles" : ["server_crl.pem"],"managementTlsCaFile" : ["management_ca.pem"],"managementTlsCert" : "security/certs/management/server.pem","managementTlsPk" : "security/keys/management/server.key.pem","managementTlsPkPwd" : "security/pass/management/key_pwd.txt","managementTlsCrlPath" : "security/management/certs/","managementTlsCrlFiles" : ["server_crl.pem"],"kmcKsfMaster" : "tools/pmt/master/ksfa","kmcKsfStandby" : "tools/pmt/standby/ksfb","inferMode" : "standard","interCommTLSEnabled" : true,"interCommPort" : 1121,"interCommTlsCaPath" : "security/grpc/ca/","interCommTlsCaFiles" : ["ca.pem"],"interCommTlsCert" : "security/grpc/certs/server.pem","interCommPk" : "security/grpc/keys/server.key.pem","interCommPkPwd" : "security/grpc/pass/key_pwd.txt","interCommTlsCrlPath" : "security/grpc/certs/","interCommTlsCrlFiles" : ["server_crl.pem"],"openAiSupport" : "vllm"},"BackendConfig" : {"backendName" : "mindieservice_llm_engine","modelInstanceNumber" : 4,"npuDeviceIds" : [[0,1], [2,3], [4,5], [6,7]],"tokenizerProcessNumber" : 8,"multiNodesInferEnabled" : false,"multiNodesInferPort" : 1120,"interNodeTLSEnabled" : true,"interNodeTlsCaPath" : "security/grpc/ca/","interNodeTlsCaFiles" : ["ca.pem"],"interNodeTlsCert" : "security/grpc/certs/server.pem","interNodeTlsPk" : "security/grpc/keys/server.key.pem","interNodeTlsPkPwd" : "security/grpc/pass/mindie_server_key_pwd.txt","interNodeTlsCrlPath" : "security/grpc/certs/","interNodeTlsCrlFiles" : ["server_crl.pem"],"interNodeKmcKsfMaster" : "tools/pmt/master/ksfa","interNodeKmcKsfStandby" : "tools/pmt/standby/ksfb","ModelDeployConfig" :{"maxSeqLen" : 13000,"maxInputTokenLen" : 4096,"truncation" : false,"ModelConfig" : [{"modelInstanceType" : "Standard","modelName" : "deepseek-32b","modelWeightPath" : "/storage/llm/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B","worldSize" : 2,"cpuMemSize" : 100,"npuMemSize" : 10,"backendType" : "atb","trustRemoteCode" : false}]},"ScheduleConfig" :{"templateType" : "Standard","templateName" : "Standard_LLM","cacheBlockSize" : 128,"maxPrefillBatchSize" : 50,"maxPrefillTokens" : 16384,"prefillTimeMsPerReq" : 150,"prefillPolicyType" : 0,"decodeTimeMsPerReq" : 50,"decodePolicyType" : 0,"maxBatchSize" : 200,"maxIterTimes" : 4096,"maxPreemptCount" : 0,"supportSelectBatch" : false,"maxQueueDelayMicroseconds" : 5000}}
}

服务启动项参数说明

详细查看官网
配置参数说明-快速开始-MindIE Service开发指南-服务化集成部署-MindIE1.0.RC2开发文档-昇腾社区

OtherParam参数

配置项取值类型取值范围配置说明
ResourceParam
cacheBlockSizeuint32_t[1, 128]kvcache block的size大小。必填,默认值:128;建议值:128,其他值建议取为2的n次幂。
LogParam
logLevelstring"Verbose""Info""Warning""Error""None""Verbose":打印Verbose、Info、Warning和Error级别的日志。"Info":打印Info、Warning和Error级别的日志。"Warning":打印Warning和Error级别的日志。"Error":打印Error级别的日志。"None":不打印日志。必填,默认值:"Info"。
logPathstring日志文件路径,长度<=4096。支持绝对和相对路径。如果配置为相对路径,则代码中会取工程目录,最后拼接而成。例如,假设MindIE Service的安装路径为“/opt/Ascend-mindie-service{version}linux-x86_64/”,则默认的日志绝对路径为“/opt/Ascend-mindie-service{version}linux-x86_64/logs/mindservice.log”。若配置路径不满足要求,则使用默认路径:“工程路径/logs/mindservice.log”。必填,默认值:"logs/mindservice.log"。
ServeParam
ipAddressstringIPv4地址。EndPoint提供的业务面RESTful接口绑定的IP地址。全零侦听会导致三面隔离失效,不满足安全配置要求,禁止绑定IP地址为0.0.0.0。如果存在环境变量MIES_CONTAINER_IP,则优先取环境变量值作为业务面IP地址。如果不存在环境变量MIES_CONTAINER_IP,则取该配置值。必填,默认值:"127.0.0.1"。
managementIpAddressstringIPv4地址。EndPoint提供的管理面RESTful接口绑定的IP地址。全零侦听会导致三面隔离失效,不满足安全配置要求,禁止绑定IP地址为0.0.0.0。如果该环境变量MIES_CONTAINER_MANAGEMENT_IP存在,则直取环境变量值作为管理面IP地址。如果“managementIpAddress”字段存在,则取字段本身值;否则取“ipAddress”字段的值作为管理面IP地址。如果采用多IP地址的方案,对“ipAddress”和“managementAddress”的初始值都需要做相应的修改。选填,默认值:"127.0.0.2"。
portint32_t[1024, 65535]EndPoint提供的业务面RESTful接口绑定的端口号。如果采用物理机/宿主机IP地址通信,请自行保证端口号无冲突。必填,默认值:1025。
managementPortint32_t[1024, 65535]EndPoint提供的管理面(管理面接口参考表1)接口绑定的端口号。业务面与管理面可采用四种方案:单IP地址单端口号(推荐)单IP地址多端口号多IP地址单端口号多IP地址多端口号在单卡节点中,不能使用多IP地址单端口号的方案,会因端口号占用而无法启动。选填,默认值:1026。
maxLinkNumuint32_t[1, 1000]RESTful接口请求并发数,EndPoint支持的最大并发请求数。必填,默认值:1000。
httpsEnabledbooltruefalse是否开启https通信。true:开启https通信。false:关闭https通信。必填,默认值:true,建议值:true,取值为false时,忽略后续https通信相关参数。
tlsCaPathstring建议tlsCaPath+tlsCaFile路径长度<=4096。实际路径为工程路径+tlsCaPath,上限限制与操作系统有关,最小值为1。根证书路径,只支持软件包安装路径下的相对路径。“httpsEnabled”=true生效,生效后必填,默认值:"security/ca/"。
tlsCaFileset--string建议tlsCaPath+tlsCaFile路径长度<=4096。不可为空,并且tlsCaPath+tlsCaFile路径长度上限与操作系统有关,最小值为1。业务面根证书名称列表。“httpsEnabled”=true生效,生效后必填,默认值:["ca.pem"]。
tlsCertstring建议文件路径长度<=4096。实际路径为工程路径+tlsCert,上限限制与操作系统有关,最小值为1。业务面服务证书文件路径,只支持软件包安装路径下的相对路径。“httpsEnabled”=true生效,生效后必填,默认值:"security/certs/server.pem"。
tlsPkstring建议文件路径长度<=4096。实际路径为工程路径+tlsPk,上限限制与操作系统有关,最小值为1。业务面服务证书私钥文件路径,证书私钥的长度要求>=3072,只支持软件包安装路径下的相对路径。“httpsEnabled”=true生效,生效后必填,默认值:"security/keys/server.key.pem"。
tlsPkPwdstring文件路径长度<=4096。支持为空;若非空,则实际路径为工程路径+tlsPkPwd,上限限制与操作系统有关,最小值为1。业务面服务证书私钥加密密钥文件路径,只支持软件包安装路径下的相对路径。“httpsEnabled”=true生效,生效后选填,默认值:"security/pass/key_pwd.txt"。若私钥经过加密但是未提供此文件,系统启动时会要求用户在交互窗口输入私钥加密口令。
tlsCrlstring建议文件路径长度<=4096。支持为空;若非空,则实际路径为工程路径+tlsCrl,上限限制与操作系统有关,最小值为1。业务面服务证书吊销列表文件路径,只支持软件包安装路径下的相对路径。“httpsEnabled”=true生效,生效后必填,默认值:"security/certs/server_crl.pem"。“httpsEnabled”=false不启用吊销列表。“tlsCrl”的值只能配套“tlsCaFile”文件列表中的第一个CA文件。
managementTlsCaFileset--string建议tlsCaPath+managementTlsCaFile路径长度<=4096。不可为空,并且tlsCaPath+managementTlsCaFile路径长度上限与操作系统有关,最小值为1。管理面根证书名称列表,当前管理面证书和业务面证书放在同一个路径(tlsCaPath)下。“httpsEnabled”=true且“ipAddress”!=“managementIpAddress”生效,生效后必填,默认值:["management_ca.pem"]。
managementTlsCertstring建议文件路径长度<=4096。实际路径为工程路径+managementTlsCert,上限限制与操作系统有关,最小值为1。管理面服务证书文件路径,只支持软件包安装路径下的相对路径。“httpsEnabled”=true且“ipAddress”!=“managementIpAddress”生效,生效后必填,默认值:"security/certs/management_server.pem"。
managementTlsPkstring建议文件路径长度<=4096。实际路径为工程路径+managementTlsPk,上限限制与操作系统有关,最小值为1。管理面服务证书私钥文件路径,证书私钥的长度要求>=3072,只支持软件包安装路径下的相对路径。“httpsEnabled”=true且“ipAddress”!=“managementIpAddress”生效,生效后必填,默认值:"security/keys/management_server.key.pem"。
managementTlsPkPwdstring文件路径长度<=4096。支持为空;若非空,则实际路径为工程路径+managementTlsPkPwd,上限限制与操作系统有关,最小值为1管理面服务证书私钥加密密钥文件路径,只支持软件包安装路径下的相对路径。“httpsEnabled”=true且“ipAddress”!=“managementIpAddress”生效,生效后选填,默认值:"security/pass/management/key_pwd.txt"。若私钥经过加密但是未提供此文件,系统启动时会要求用户在交互窗口输入私钥加密口令。
managementTlsCrlstring建议文件路径长度<=4096。支持为空;若非空,则实际路径为工程路径+managementTlsCrl,上限限制与操作系统有关,最小值为1。管理面证书吊销列表文件路径,只支持软件包安装路径下的相对路径。“httpsEnabled”=true且“ipAddress”!=“managementIpAddress”生效,生效后必填,默认值:"security/certs/management_server_crl.pem"。“httpsEnabled”=false不启用吊销列表。“managementTlsCrl”的值只能配套“managementTlsCaFile”文件列表中的第一个CA文件。
kmcKsMasterstring建议文件路径长度<=4096。实际路径为工程路径+kmcKsMaster,上限限制与操作系统有关,最小值为1。KMC密钥库文件路径,只支持软件包安装路径下的相对路径。“httpsEnabled”=true生效,生效后必填,默认值:"tools/pmt/master/ksfa"。
kmcKsStandbystring建议文件路径长度<=4096。实际路径为工程路径+kmcKsStandby,上限限制与操作系统有关,最小值为1。KMC密钥库备份文件路径,只支持软件包安装路径下的相对路径。“httpsEnabled”=true生效,生效后必填,默认值:"tools/pmt/standby/ksfb"。
multiNodesInferPortuint32_t[1024, 65535]跨机通信的端口号,多机推理场景使用。选填,默认值:1120。
interNodeTLSEnabledbooltruefalse多机推理时,跨机通信是否开启证书安全认证。true:开启证书安全认证。false:关闭证书安全认证。选填,默认值:true。取值为false时,忽略后续参数。
interNodeTlsCaFilestring建议文件路径长度<=4096。实际路径为工程路径+interNodeTlsCaFile,上限限制与操作系统有关,最小值为1。根证书名称路径,只支持软件包安装路径下的相对路径。“interNodeTLSEnabled”=true生效,生效后必填,默认值:"security/ca/ca.pem"。
interNodeTlsCertstring建议文件路径长度<=4096。实际路径为工程路径+interNodeTlsCert,上限限制与操作系统有关,最小值为1。服务证书文件路径,只支持软件包安装路径下的相对路径。“interNodeTLSEnabled”=true生效,生效后必填,默认值:"security/certs/server.pem"。
interNodeTlsPkstring建议文件路径长度<=4096。实际路径为工程路径+interNodeTlsPk,上限限制与操作系统有关,最小值为1。服务证书私钥文件路径,只支持软件包安装路径下的相对路径。“interNodeTLSEnabled”=true生效,生效后必填,默认值:"security/keys/server.key.pem"。
interNodeTlsPkPwdstring建议文件路径长度<=4096。支持为空;若非空,则实际路径为工程路径+interNodeTlsPkPwd,上限限制与操作系统有关,最小值为1。服务证书私钥加密密钥文件路径,只支持软件包安装路径下的相对路径。“interNodeTLSEnabled”=true生效,生效后必填,默认值:"security/pass/mindie_server_key_pwd.txt"。
interNodeKmcKsfMasterstring建议文件路径长度<=4096。实际路径为工程路径+interNodeKmcKsfMaster,上限限制与操作系统有关,最小值为1。KMC密钥库文件路径,只支持软件包安装路径下的相对路径。“interNodeTLSEnabled”=true生效,生效后必填,默认值:"tools/pmt/master/ksfa"。
interNodeKmcKsfStandbystring建议文件路径长度<=4096。实际路径为工程路径+interNodeKmcKsfStandby,上限限制与操作系统有关,最小值为1。KMC密钥库备份文件路径,只支持软件包安装路径下的相对路径。“interNodeTLSEnabled”=true生效,生效后必填,默认值:"tools/pmt/standby/ksfb"。

说明

  • 如果网络环境不安全,不开启https通信,即“httpsEnabled”=“false”时,会存在较高的网络安全风险。
  • 如果推理服务所在的计算节点的网络为跨公网和局域网,绑定0.0.0.0的IP地址可能导致网络隔离失效,存在较大安全风险。故该场景下禁止EndPoint的IP地址绑定为0.0.0.0。
  • 如果配置了相同的管理面和业务面的IP地址,会导致隔离失效。

WorkFlowParam参数

配置项取值类型取值范围配置说明
TemplateParam
templateTypestring当前取值只能为:"Standard"普通推理。必填,默认值:"Standard"。
templateNamestring由大写字母、小写字母和下划线组成,且不以下划线作为开头和结尾,字符串长度小于或等于256。工作流名称。必填,默认值:"Standard_llama"。

ModelDeployParam参数

配置项取值类型取值范围配置说明
engineNamestring长度1~50,只支持小写字母加下划线。且不以下划线作为开头和结尾。根据engineName找对应的so文件。必填,默认值:"mindieservice_llm_engine"。
modelInstanceNumberuint32_t[1, 10]模型实例个数。必填,默认值:1。
tokenizerProcessNumberuint32_t[1, 32]tokenizer进程数。选填,默认值:8。
maxSeqLenuint32_t上限根据显存和用户需求来决定,最小值需大于0。最大序列长度。输入的长度+输出的长度<=maxSeqLen,用户根据自己的推理场景选择maxSeqLen。如果maxSeqLen大于模型支持的最大序列长度,可能会影响推理精度。必填,默认值:2560。
npuDeviceIdsset-set<size_t>根据模型和环境的实际情况来决定。表示启用哪几张卡。对于每个模型实例分配的npuIds。多机推理场景下该值无效,每个节点上使用的npuDeviceIds根据ranktable计算获得。必填,默认值:[[0,1,2,3]]。
multiNodesInferEnabledbooltruefalsefalse:单机推理。true:多机推理。选填,默认值:false。
ModelParam
modelInstanceTypestring"Standard""StandardMock"模型类型。"Standard":普通推理。"StandardMock":假模型。选填,默认值:"Standard"。
modelNamestring由大写字母、小写字母、数字、中划线、点和下划线组成,且不以中划线、点和下划线作为开头和结尾,字符串长度小于或等于256。模型名称。必填,默认值:"llama_65b"。
modelWeightPathstring文件绝对路径长度的上限与操作系统有关,最小值为1。模型权重路径。程序会读取该路径下的config.json中torch_dtype和vocab_size字段的值,需保证路径和相关字段存在。必填,默认值:"/data/atb_testdata/weights/llama1-65b-safetensors"。该路径会进行安全校验,必须使用绝对路径,且和执行用户的属组和权限保持一致。
worldSizeuint32_t根据模型实际情况来决定。每一套模型参数中worldSize必须与使用的NPU数量相等。启用几张卡推理。目前llama-65b至少启用四张NPU卡。多机推理场景下该值无效,worldSize根据ranktable计算获得。必填,默认值:4。
cpuMemSizeuint32_t上限根据显存和用户需求来决定。只有当maxPreemptCount为0时,才可以取值为0。CPU中可以用来申请kv cache的size上限。必填,默认值:5,建议值:5,单位:GB。
npuMemSizeuint32_t上限根据显存和用户需求来决定,下限大于0。NPU中可以用来申请kv cache的size上限。必填,默认值:8,建议值:8,单位:GB。快速计算公式:npuMemSize=(单卡总空闲-权重/NPU卡数-后处理占用)*系数,其中系数取0.8。
backendTypestring"atb""ms"对接的后端类型。必填,默认值:"atb"。
pluginParamsstring根据并行解码实际所需填写一个json字符串。选填,默认值:""。

ScheduleParam参数

配置项取值类型取值范围配置说明
maxPrefillBatchSizeuint32_t[1, maxBatchSize]最大prefill batch size。maxPrefillBatchSize和maxPrefillTokens谁先达到各自的取值就完成本次组batch。该参数主要是在明确需要限制prefill阶段batch size的场景下使用,否则可以设置为0(此时引擎将默认取maxBatchSize值)或与maxBatchSize值相同。必填,默认值:50。
maxPrefillTokensuint32_t[5120, 512000],且必须大于或等于maxSeqLen的取值。每次prefill时,当前batch中所有input token总数,不能超过maxPrefillTokens。maxPrefillTokens和maxPrefillBatchSize谁先达到各自的取值就完成本次组batch。必填,默认值:8192。
prefillTimeMsPerRequint32_t[0, 1000]与decodeTimeMsPerReq比较,计算当前应该选择prefill还是decode。单位:ms,当“supportSelectBatch”=true时有效。其调度策略流程图请参见图1。必填,默认值:150。
prefillPolicyTypeuint32_t013prefill阶段的调度策略,其调度策略流程图请参见图2。0:FCFS,先来先服务。1:STATE,prefill阶段等同于FCFS策略。3:MLFQ,多级反馈队列。其中,3是0/1的组合。必填,默认值:0。
decodeTimeMsPerRequint32_t[0, 1000]与prefillTimeMsPerReq比较,计算当前应该选择prefill还是decode。单位:ms,当“supportSelectBatch”=true时有效。其调度策略流程图请参见图1。必填,默认值:50。
decodePolicyTypeuint32_t013decode阶段的调度策略。其调度策略流程图请参见图2。0:FCFS,先来先服务。1:STATE,decode阶段优先执行未被抢占和换出的请求。3:MLFQ,多级反馈队列。其中,3是0/1的组合。必填,默认值:0。
maxBatchSizeuint32_t[1, 5000],且必须大于或等于maxPreemptCount的取值。最大decode batch size。首先计算block_num:Total Block Num = Floor(NPU显存/(模型网络数cacheBlockSize模型注意力头数注意力头大小Cache类型字节数Cache数)),其中,Cache数=2;在tensor并行的情况下,block_numworld_size为实际的分配block数。如果是多卡,公式中的模型注意力头数注意力大小的值需要均摊在每张卡上,即“模型注意力头数注意力大小/卡数”。公式中的Floor表示计算结果向下取整。为每个请求申请的block数量Block Num=Ceil(输入Token数/Block Size)+Ceil(最大输出Token数/Block Size)。输入Token数:输入(字符串)做完tokenizer后的tokenID个数;最大输出Token数:模型推理最大迭代次数和最大输出长度之间取较小值。公式中的Ceil表示计算结果向上取整。maxBatchSize=Total Block Num/Block Num。必填,默认值:200。
maxIterTimesuint32_t[1, maxSeqLen-1]迭代次数,即一句话最大可生成长度。与允许推理生成的最大token个数max_tokens(或max_new_tokens)取较小值作为最大可生成长度。必填,默认值:512。
maxPreemptCountint32_t[0, maxBatchSize],当取值大于0时,cpuMemSize取值不可为0。每一批次最大可抢占请求的上限,即限制一轮调度最多抢占请求的数量,最大上限为maxBatchSize,取值大于0则表示开启可抢占功能。必填,默认值:0。
supportSelectBatchbooltruefalsebatch选择策略。false:表示每一轮调度时,优先调度和执行prefill阶段的请求。true:表示每一轮调度时,根据当前prefill与decode请求的数量,自适应调整prefill和decode阶段请求调度和执行的先后顺序。必填,默认值:false。
maxQueueDelayMicrosecondsuint32_t[500, 1000000]队列等待时间,单位:us。必填,默认值:5000。

图1 调度策略和执行先后顺序流程图

图2 prefill和decode阶段的调度策略流程图

启动模型

拉起服务化接口

cd /usr/local/Ascend/mindie/latest/mindie-service/bin
./mindieservice_daemon

后台启动

cd $MIES_INSTALL_PATH
nohup ./bin/mindieservice_daemon > output.log 2>&1 &
tail -f output.log# nuhup 开启一个后台进程
[1] 107
# 杀死进程 kill 107

Daemon start success! 则为启动成功

接口测试

time curl -X POST http://127.0.0.1:1025/v1/chat/completions \-H "Accept: application/json" \-H "Content-type: application/json" \-d '{"model": "deepseek-14b","messages": [{"role": "user","content": "我有五天假期,我想去海南玩,请给我一个攻略"}],"max_tokens": 2048,"presence_penalty": 1.03,"frequency_penalty": 1.0,"seed": null,"temperature": 0.5,"top_p": 0.95,"stream": false
}' 

脚本测试(可选)

cd $ATB_SPEED_HOME_PATH
python examples/run_pa.py --model_path /storage/llm/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B

并发测试

14B - 单卡运行

八张卡 八个实例

设备模型上下文(输出+输出长度)并发循环次数并发请求总输出速率(tokens/s)单个请求速率的平均请求超时个数(超过60s的请求)
910B3 * 8deepseek-14b20481133.0333.030
910B3 * 8deepseek-14b40961131.9131.910
910B3 * 8deepseek-14b81921131.0831.080
910B3 * 8deepseek-14b204841101.6332.930
910B3 * 8deepseek-14b409641113.4331.980
910B3 * 8deepseek-14b81924194.8631.110
910B3 * 8deepseek-14b204881213.0531.990
910B3 * 8deepseek-14b409681185.0830.090
910B3 * 8deepseek-14b819281154.0829.450
910B3 * 8deepseek-14b2048161284.9931.000
910B3 * 8deepseek-14b4096161279.6029.440
910B3 * 8deepseek-14b8192161346.7827.920
910B3 * 8deepseek-14b2048321579.9829.460
910B3 * 8deepseek-14b4096321575.0826.800
910B3 * 8deepseek-14b8192321560.2924.920
910B3 * 8deepseek-14b2048641932.1524.590
910B3 * 8deepseek-14b40966411118.5924.520
910B3 * 8deepseek-14b8192641816.2121.982
910B3 * 8deepseek-14b20489611294.4525.580
910B3 * 8deepseek-14b40969611437.1521.762
910B3 * 8deepseek-14b81929611291.1718.785
910B3 * 8deepseek-14b204812811307.5320.165
910B3 * 8deepseek-14b409612811560.0016.8128
910B3 * 8deepseek-14b819212811348.4113.0637
910B3 * 8deepseek-14b204819611417.7612.3077
910B3 * 8deepseek-14b40961961404.822.84171
910B3 * 8deepseek-14b81921961521.182.94162

32B - 双卡并行

八张卡 四个实例

设备模型上下文(输出+输出长度)并发循环次数并发请求总输出速率(tokens/s)单个请求速率的平均请求超时个数(超过60s的请求)
910B3 * 8deepseek-32b20481127.6427.640
910B3 * 8deepseek-32b40961126.4326.430
910B3 * 8deepseek-32b81921125.0925.090
910B3 * 8deepseek-32b20484180.3126.230
910B3 * 8deepseek-32b40964167.8623.030
910B3 * 8deepseek-32b81924181.5423.390
910B3 * 8deepseek-32b204881147.1523.170
910B3 * 8deepseek-32b409681131.0622.090
910B3 * 8deepseek-32b819281123.2320.390
910B3 * 8deepseek-32b2048161279.6921.080
910B3 * 8deepseek-32b4096161161.0819.832
910B3 * 8deepseek-32b8192161223.3619.380
910B3 * 8deepseek-32b2048321312.5421.060
910B3 * 8deepseek-32b4096321367.0318.931
910B3 * 8deepseek-32b8192321273.4318.205
910B3 * 8deepseek-32b2048641762.2620.520
910B3 * 8deepseek-32b4096641521.3216.756
910B3 * 8deepseek-32b8192641442.4314.4815
910B3 * 8deepseek-32b2048961866.9718.461
910B3 * 8deepseek-32b4096961905.7511.6520
910B3 * 8deepseek-32b8192961471.275.5950
910B3 * 8deepseek-32b20481281522.607.0075
910B3 * 8deepseek-32b40961281117.510.99118
910B3 * 8deepseek-32b819212810.000.00128
910B3 * 8deepseek-32b204819611345.3214.6991
910B3 * 8deepseek-32b40961961925.3011.43146
910B3 * 8deepseek-32b81921961755.339.04166

并发测试脚本代码

找一个文件夹,创建、执行并发请求脚本

  1. python model_request_test.py
  2. python statistic.py
  • 新建请求脚本

vi model_request_test.py

# -*- coding: utf-8 -*-
# @Time    : 2025/2/14 14:29import os.pathimport asyncio
import aiohttp
import time
import json
import logging# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')test_context = """
我们过了江,进了车站。我买票,他忙着照看行李。行李太多了,得向脚夫⑾行些小费才可过去。他便又忙着和他们讲价钱。我那时真是聪明过分,总觉他说话不大漂亮,非自己插嘴不可,但他终于讲定了价钱;就送我上车。他给我拣定了靠车门的一张椅子;我将他给我做的紫毛大衣铺好座位。他嘱我路上小心,夜里要警醒些,不要受凉。又嘱托茶房好好照应我。我心里暗笑他的迂;他们只认得钱,托他们只是白托!而且我这样大年纪的人,难道还不能料理自己么?我现在想想,我那时真是太聪明了。
我说道:“爸爸,你走吧。”他往车外看了看,说:“我买几个橘子去。你就在此地,不要走动。”我看那边月台的栅栏外有几个卖东西的等着顾客。走到那边月台,须穿过铁道,须跳下去又爬上去。父亲是一个胖子,走过去自然要费事些。我本来要去的,他不肯,只好让他去。我看见他戴着黑布小帽,穿着黑布大马褂⑿,深青布棉袍,蹒跚⒀地走到铁道边,慢慢探身下去,尚不大难。可是他穿过铁道,要爬上那边月台,就不容易了。他用两手攀着上面,两脚再向上缩;他肥胖的身子向左微倾,显出努力的样子。这时我看见他的背影,我的泪很快地流下来了。我赶紧拭干了泪。怕他看见,也怕别人看见。我再向外看时,他已抱了朱红的橘子往回走了。过铁道时,他先将橘子散放在地上,自己慢慢爬下,再抱起橘子走。到这边时,我赶紧去搀他。他和我走到车上,将橘子一股脑儿放在我的皮大衣上。于是扑扑衣上的泥土,心里很轻松似的。过一会儿说:“我走了,到那边来信!”我望着他走出去。他走了几步,回过头看见我,说:“进去吧,里边没人。”等他的背影混入来来往往的人里,再找不着了,我便进来坐下,我的眼泪又来了。
"""# 输入文本列表  此处为示例,实际测试请使用长度在 1800、3500、7000 字左右的文本作为输入  使得上下文长度在 2048、4096、8192 字左右
input_texts = [test_context * (2048 // len(test_context)) + "\n====\n总结以上文本为字数200字的摘要。",test_context * (4096 // len(test_context)) + "\n====\n总结以上文本为字数500字的摘要。",test_context * (8192 // len(test_context)) + "\n====\n总结以上文本为字数1000字的摘要。",
]# 并发请求列表
concurrency_levels = [1, 4, 8, 16, 32, 64, 96, 128, 196]
# concurrency_levels = [96, 128, 196]
# concurrency_levels = [1]# 循环次数
loop_count = 1# 请求接口地址
url = "http://127.0.0.1:1025/v1/chat/completions"# 设备和模型信息
device = "910B3 * 8"
# model = "DeepSeek-R1-Distill-32B"
model = "deepseek-14b"  # 此处对应配置文件中的 ModelDeployConfig.ModelConfig.modelNameif not os.path.exists(model):os.mkdir(model)async def make_request(session, input_text):# logging.info("开始单个请求")headers = {"Accept": "application/json","Content-type": "application/json"}data = {"model": model,"messages": [{"role": "user", "content": input_text}],"max_tokens": 2048,"presence_penalty": 1.03,"frequency_penalty": 1.0,"seed": None,"temperature": 0.5,"top_p": 0.95,"stream": True}start_time = time.time()try:async with session.post(url, headers=headers, json=data, timeout=60) as response:output_tokens = 0async for chunk in response.content.iter_chunked(65535):try:chunk_str = chunk.decode('utf-8').strip()if chunk_str.startswith("data: "):chunk_str = chunk_str[len("data: "):]chunk_data = json.loads(chunk_str)"""data: {"id":"endpoint_common_34","object":"chat.completion.chunk","created":1739519727,"model":"deepseek-32b","usage":{"prompt_tokens":6,"completion_tokens":27,"total_tokens":33},"choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":"stop"}]}"""output_tokens += 1except (json.JSONDecodeError, UnicodeDecodeError):continueend_time = time.time()elapsed_time = end_time - start_timeprint(f"elapsed_time: 0.0614")output_rate = output_tokens / elapsed_time if elapsed_time > 0 else 0logging.info(f"单个请求完成,输出 tokens: {output_tokens},耗时: {elapsed_time:.2f}s,输出速率: {output_rate:.2f} tokens/s")return output_tokens, elapsed_time, output_rateexcept asyncio.TimeoutError:logging.warning("单个请求超时")return 0, 60, 0except Exception as e:print(f"ERROR: {e}")return 0, 60, 0async def run_concurrent_tests(concurrency, input_text):logging.info(f"开始并发数为 {concurrency} 的测试")async with aiohttp.ClientSession() as session:tasks = [make_request(session, input_text) for _ in range(concurrency)]results = await asyncio.gather(*tasks)total_output_tokens = sum([result[0] for result in results])total_elapsed_time = max([result[1] for result in results])total_output_rate = total_output_tokens / total_elapsed_time if total_elapsed_time > 0 else 0average_single_rate = sum([result[2] for result in results]) / concurrencytimeout_count = sum([1 for result in results if result[1] >= 60])logging.info(f"并发数为 {concurrency} 的测试完成,总输出 tokens: {total_output_tokens},总耗时: {total_elapsed_time:.2f}s,"f"并发请求总输出速率: {total_output_rate:.2f} tokens/s,单个请求速率平均: {average_single_rate:.2f} tokens/s,超时个数: {timeout_count}")return total_output_rate, average_single_rate, timeout_countasync def main():print("|设备|模型|上下文(输出+输出长度)|并发|循环次数|并发请求总输出速率(tokens/s)|单个请求速率的平均|请求超时个数(超过60s的请求)|")print("| ------| ------| --------| ------| ----------| ------------------| ----------| --------------|")for concurrency in concurrency_levels:all_results = []for i, input_text in enumerate(input_texts):input_length = len(input_text)total_output_rate, average_single_rate, timeout_count = await run_concurrent_tests(concurrency, input_text)context = 2048 * (2 ** i)print(f"测试 {i + 1}/{len(input_texts)} 完成,并发数为 {concurrency},循环次数为 {loop_count}")result = {"设备": device,"模型": model,"上下文(输出+输出长度)": context,"并发": concurrency,"循环次数": loop_count,"并发请求总输出速率(tokens/s)": total_output_rate,"单个请求速率的平均": average_single_rate,"请求超时个数(超过60s的请求)": timeout_count}all_results.append(result)print(f"|{device}|{model}|{context}|{concurrency}|{loop_count}|{total_output_rate:.2f}|{average_single_rate:.2f}|{timeout_count}|")# 按并发数保存到 JSON 文件filename = f'{model}/test_results_concurrency_{concurrency}.json'with open(filename, 'w', encoding='utf-8') as f:json.dump(all_results, f, ensure_ascii=False, indent=4)logging.info(f"并发数为 {concurrency} 的测试结果已保存到 {filename}")if __name__ == "__main__":asyncio.run(main())
  • 新建统计脚本

vi statistic.py

# -*- coding: utf-8 -*-
# @Time    : 2025/2/17 8:32
import json# 并发请求列表
concurrency_levels = [1, 4, 8, 16, 32, 64, 96, 128, 196]
version = 'deepseek-14b'   # 此处对应配置文件中的 ModelDeployConfig.ModelConfig.modelName# 汇总所有结果
all_results = []
for concurrency in concurrency_levels:filename = f'{version}/test_results_concurrency_{concurrency}.json'try:with open(filename, 'r', encoding='utf-8') as f:results = json.load(f)all_results.extend(results)except FileNotFoundError:print(f"未找到文件 {filename},请确保之前的测试已成功保存结果。")# 生成 Markdown 表格表头
markdown_table = "|设备|模型|上下文(输出+输出长度)|并发|循环次数|并发请求总输出速率(tokens/s)|单个请求速率的平均|请求超时个数(超过60s的请求)|\n"
markdown_table += "| ------| ------| --------| ------| ----------| ------------------| ----------| --------------|\n"# 填充表格内容
for result in all_results:markdown_table += f"|{result['设备']}|{result['模型']}|{result['上下文(输出+输出长度)']}|{result['并发']}|{result['循环次数']}|{result['并发请求总输出速率(tokens/s)']:.2f}|{result['单个请求速率的平均']:.2f}|{result['请求超时个数(超过60s的请求)']}|\n"# 输出 Markdown 表格
print(markdown_table)# 保存 Markdown 表格到文件
with open(f'{version}/summary_table.md', 'w', encoding='utf-8') as f:f.write(markdown_table)

报错

Operation not permitted

[root@pm-a813-005 bin]# ./mindieservice_daemon
terminate called after throwing an instance of 'system_error'what():  Operation not permitted

模型路径的权限设置错误

chmod -R 755 /path-to-weights

参考 mindie/README.md · Ascend/ascend-docker-image - Gitee.com

ConnectionRefusedError

[root@pm-a813-005 /]# vi /usr/local/Ascend/mindie/latest/mindie-service/conf/config.json
[root@pm-a813-005 /]# cd /usr/local/Ascend/mindie/latest/mindie-service/bin
[root@pm-a813-005 bin]# ./mindieservice_daemon
...
Traceback (most recent call last):File "/usr/lib64/python3.11/multiprocessing/process.py", line 314, in _bootstrapself.run()File "/usr/lib64/python3.11/multiprocessing/process.py", line 108, in runself._target(*self._args, **self._kwargs)File "/usr/local/Ascend/ascend-toolkit/latest/python/site-packages/tbe/common/repository_manager/route.py", line 71, in wrapperraise expFile "/usr/local/Ascend/ascend-toolkit/latest/python/site-packages/tbe/common/repository_manager/route.py", line 63, in wrapperfunc(*args, **kwargs)File "/usr/local/Ascend/ascend-toolkit/latest/python/site-packages/tbe/common/repository_manager/route.py", line 268, in task_distributekey, func_name, detail = resource_proxy[TASK_QUEUE].get()^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "<string>", line 2, in getFile "/usr/lib64/python3.11/multiprocessing/managers.py", line 822, in _callmethodkind, result = conn.recv()^^^^^^^^^^^File "/usr/lib64/python3.11/multiprocessing/connection.py", line 250, in recvbuf = self._recv_bytes()^^^^^^^^^^^^^^^^^^File "/usr/lib64/python3.11/multiprocessing/connection.py", line 430, in _recv_bytesbuf = self._recv(4)^^^^^^^^^^^^^File "/usr/lib64/python3.11/multiprocessing/connection.py", line 395, in _recvchunk = read(handle, remaining)^^^^^^^^^^^^^^^^^^^^^^^
ConnectionResetError: [Errno 104] Connection reset by peer
/usr/lib64/python3.11/multiprocessing/resource_tracker.py:254: UserWarning: resource_tracker: There appear to be 30 leaked semaphore objects to clean up at shutdownwarnings.warn('resource_tracker: There appear to be %d '
/usr/lib64/python3.11/multiprocessing/resource_tracker.py:254: UserWarning: resource_tracker: There appear to be 30 leaked semaphore objects to clean up at shutdownwarnings.warn('resource_tracker: There appear to be %d '
Daemon is killing...
Killed

当前镜像 和 宿主机服务器的 驱动版本不对应,前往官网换个镜像

引用pytorch

警告而已,影响不大

[root@pm-a813-005 atb-models]# python
Python 3.11.6 (main, Nov 27 2024, 18:16:08) [GCC 12.3.1 (openEuler 12.3.1-38.oe2403)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch>>> import torch_npu
/usr/local/lib64/python3.11/site-packages/torch_npu/__init__.py:248: UserWarning: On the interactive interface, the value of TASK_QUEUE_ENABLE is set to 0 by default.                      Do not set it to 1 to prevent some unknown errorswarnings.warn("On the interactive interface, the value of TASK_QUEUE_ENABLE is set to 0 by default. \
>>> 

the size of npuDeviceIds (subset) does not equal to worldSize

the size of npuDeviceIds (subset) does not equal to worldSize
ERR: Failed to init endpoint! Please check the service log or console output.
Killed

此错误表明 npuDeviceIds​(可能是 NPU 设备 ID 的子集)的数量与 worldSize​ 不匹配。在分布式计算的场景下,worldSize​ 通常代表参与计算的所有进程或设备的总数,而 npuDeviceIds​ 则是指定要使用的 NPU 设备的 ID 列表。当这两者的数量不一致时,就会触发该错误。

vi /usr/local/Ascend/mindie/latest/mindie-service/conf/config.json

...
"BackendConfig" : {"backendName" : "mindieservice_llm_engine","modelInstanceNumber" : 1,"npuDeviceIds" : [[0]],....
"ModelConfig" : [{"modelInstanceType" : "Standard","modelName" : "deepseek-14b","modelWeightPath" : "/storage/llm/deepseek-ai/DeepSeek-R1-Distill-Qwen-14B","worldSize" : 1,  # 此处数量要与 npuDeviceIds 一致
....

Failed to init endpoint

The serverConfig.kmcKsfMaster path is invalid by: The input file: ksfa is not a regular file or not exists
The serverConfig.kmcKsfStandby path is invalid by: The input file: ksfb is not a regular file or not exists
The serverConfig_.tlsCert path is invalid by: The input file: server.pem is not a regular file or not exists
ERR: serverConfig_.tlsCrlFiles file not exit .
The serverConfig_.tlsCaFile path is invalid by: The input file: ca.pem is not a regular file or not exists
The serverConfig_.tlsPk path is invalid by: The input file: server.key.pem is not a regular file or not exists
The serverConfig_.tlsPkPwd path is invalid by: The input file: key_pwd.txt is not a regular file or not exists
The ServerConfig.managementTlsCert path is invalid by: The input file: server.pem is not a regular file or not exists
The ServerConfig.managementTlsCrlPath path is not a dir by: 
ERR: serverConfig_.managementTlsCrlFiles file not exit .
ERR: serverConfig_.managementTlsCaFile file not exit .
The ServerConfig.managementTlsPk path is invalid by: The input file: server.key.pem is not a regular file or not exists
The ServerConfig.managementTlsPkPwd path is invalid by: The input file: key_pwd.txt is not a regular file or not exists
ERR: Failed to init endpoint! Please check the service log or console output.
Killed

解决方法就是取消https 启动服务

vi /usr/local/Ascend/mindie/latest/mindie-service/conf/config.json

    "ServerConfig" :{"ipAddress" : "127.0.0.1","managementIpAddress" : "127.0.0.2","port" : 1025,"managementPort" : 1026,"metricsPort" : 1027,"allowAllZeroIpListening" : false,"maxLinkNum" : 1000,"httpsEnabled" : false,  # 设置为 false 不是用https
。。。

Please check the service log or console output.

ERR: Failed to init endpoint! Please check the service log or console output. Killed

实例启动太多 共享内存不够,导致日志写入失败

解决: 减少实例数量 或者增加 增加共享内存空间
docker run .... --shm-size=10g

其他查询指令

系统架构

uname -m

NPU 信息

npu-smi info

CANN 版本

  • x86
cat /usr/local/Ascend/ascend-toolkit/latest/x86_64-linux/ascend_toolkit_install.info
  • arm
cat /usr/local/Ascend/ascend-toolkit/latest/arm64-linux/ascend_toolkit_install.info
[root@pm-a813-005 /]# cat /usr/local/Ascend/ascend-toolkit/latest/arm64-linux/ascend_toolkit_install.info
package_name=Ascend-cann-toolkit
version=8.0.0
innerversion=V100R001C20SPC001B251
compatible_version=[V100R001C15],[V100R001C17],[V100R001C18],[V100R001C19],[V100R001C20]
arch=aarch64
os=linux
path=/usr/local/Ascend/ascend-toolkit/8.0.0/aarch64-linux

基础环境搭建

获取CANN&MindIE安装包&环境准备

  • Atlas 800I A2/Atlas 300I Duo/Atlas 300 V
  • 环境准备指导

CANN安装

# 增加软件包可执行权限,{version}表示软件版本号,{arch}表示CPU架构,{soc}表示昇腾AI处理器的版本。
chmod +x ./Ascend-cann-toolkit_{version}_linux-{arch}.run
chmod +x ./Ascend-cann-kernels-{soc}_{version}_linux.run
# 校验软件包安装文件的一致性和完整性
./Ascend-cann-toolkit_{version}_linux-{arch}.run --check
./Ascend-cann-kernels-{soc}_{version}_linux.run --check
# 安装
./Ascend-cann-toolkit_{version}_linux-{arch}.run --install
./Ascend-cann-kernels-{soc}_{version}_linux.run --install# 设置环境变量
source /usr/local/Ascend/ascend-toolkit/set_env.sh

MindIE安装

# 增加软件包可执行权限,{version}表示软件版本号,{arch}表示CPU架构。
chmod +x ./Ascend-mindie_${version}_linux-${arch}.run
./Ascend-mindie_${version}_linux-${arch}.run --check# 方式一:默认路径安装
./Ascend-mindie_${version}_linux-${arch}.run --install
# 设置环境变量
cd /usr/local/Ascend/mindie && source set_env.sh# 方式二:指定路径安装
./Ascend-mindie_${version}_linux-${arch}.run --install-path=${AieInstallPath}
# 设置环境变量
cd ${AieInstallPath}/mindie && source set_env.sh

Torch_npu安装

下载 pytorch_v{pytorchversion}_py{pythonversion}.tar.gz

tar -xzvf pytorch_v{pytorchversion}_py{pythonversion}.tar.gz
# 解压后,会有whl包
pip install torch_npu-{pytorchversion}.xxxx.{arch}.whl

相关链接

  • 模型库-ModelZoo-昇腾社区
  • 模型库-魔搭社区
  • https://modelers.cn/MindIE
  • modelscope 魔搭社区模型下载
  • mindie/README.md · Ascend/ascend-docker-image - Gitee.com
  • 配置参数说明-快速开始-MindIE Service开发指南-服务化集成部署-MindIE1.0.RC2开发文档-昇腾社区
  • 单机推理-配置MindIE Server-配置MindIE-MindIE安装指南-环境准备-MindIE1.0.RC2开发文档-昇腾社区
  • DeepSeek-R1-Distill-Qwen-32B-模型库-ModelZoo-昇腾社区
  • mindie镜像版本下载
  • Altas产品查询CANN软件包版本的方法 - 华为
  • npu-smi命令介绍(适用于1.0.11-1.0.15版本) - Atlas 300I 推理卡 用户指南(型号 3010)31 - 华为​
  • 昇腾模型库

  • MindIE官方文档

  • MindIE Service开发指南

  • DeepSeek-R1模型卡片

  • DeepSeek模型量化方法介绍

  • 昇腾镜像仓库

  • 量化技术白皮书

  • Ascend/ModelZoo-PyTorch

  • 在线推理过程中可使用的环境变量配置

  • 昇腾社区资源下载

  • CANN环境准备指导

  • DeepSeek 系列模型 华为昇腾官方教程

    模型名称安装教程
    DeepSeek V3DeepSeek-V3-模型库-ModelZoo-昇腾社区
    DeepSeek R1DeepSeek-R1-模型库-ModelZoo-昇腾社区
    DeepSeek-R1-Distill-Qwen-1.5BDeepSeek-R1-Distill-Qwen-1.5B-模型库-ModelZoo-昇腾社区
    DeepSeek-R1-Distill-Qwen-7BDeepSeek-R1-Distill-Qwen-7B-模型库-ModelZoo-昇腾社区
    DeepSeek-R1-Distill-Llama-8BDeepSeek-R1-Distill-Llama-8B-模型库-ModelZoo-昇腾社区
    DeepSeek-R1-Distill-Qwen-14BDeepSeek-R1-Distill-Qwen-14B-模型库-ModelZoo-昇腾社区
    DeepSeek-R1-Distill-Qwen-32BDeepSeek-R1-Distill-Qwen-32B-模型库-ModelZoo-昇腾社区
    DeepSeek-R1-Distill-Llama-70BDeepSeek-R1-Distill-Llama-70B-模型库-ModelZoo-昇腾社区
    Janus-Pro-7BJanus-Pro-模型库-ModelZoo-昇腾社区

相关文章:

华为昇腾 910B 部署 DeepSeek-R1 蒸馏系列模型详细指南

本文记录 在 华为昇腾 910B(65GB) * 8 上 部署 DeepSeekR1 蒸馏系列模型&#xff08;14B、32B&#xff09;全过程与测试结果。 NPU&#xff1a;910B3 (65GB) * 8 &#xff08;910B 有三个版本 910B1、2、3&#xff09; 模型&#xff1a;DeepSeek-R1-Distill-Qwen-14B、DeepSeek…...

vue3项目实践心得-多次渲染同一svg + 理解v-if、transition、dom加载之间的顺序

&#x1f9e1;&#x1f9e1;需求&#x1f9e1;&#x1f9e1; 未点击查看答案按钮时&#xff0c;步骤3面板未展示内容&#xff08;v-if控制&#xff09; 点击查看答案按钮后&#xff0c;通过graphviz绘制并展示状态转换图&#xff0c;渲染在步骤2中&#xff0c;同时步骤3的v-…...

【实战项目】BP神经网络识别人脸朝向----MATLAB实现

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言&#xff0c;数据结构&#xff0c;Linux基础&#xff0c;ARM开发板&#xff0c;网络编程等领域UP&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff0…...

java数据结构_二叉树_5.5

2.7 二叉树的相关操作 1. size方法 获取二叉树元素个数 思路&#xff1a;遍历思路&#xff0c;在前面文章中&#xff0c;前序 中序 后序遍历的时候&#xff0c;会把树中的所有结点遍历一次。可以添加一个计数器&#xff0c;遍历一个结点就加一次。 于是有如下代码&#xff1…...

Deepseek-R1推理模型API接入调用指南 ChatGPT Web Midjourney Proxy 开源项目接入Deepseek教程

DeepSeek-R1和OpenAI o1模型都属于推理任务模型&#xff0c;两个模型各有优点&#xff1a;DeepSeek-R1 在后训练阶段大规模使用了强化学习技术&#xff0c;在仅有极少标注数据的情况下&#xff0c;极大提升了模型推理能力。在数学、代码、自然语言推理等任务上&#xff0c;性能…...

计算机网络(4)TCP断开

1、TCP 断开连接四次挥手流程 TCP 断开连接是通过四次挥手方式。双方都可以主动断开连接&#xff0c;断开连接后主机中的「资源」将被释放。 2、为什么 TIME_WAIT 等待的时间是 2MSL&#xff1f; 3、为什么需要 TIME_WAIT 状态&#xff1f; 4、拔掉网线后&#xff0c; 原本的 …...

科技云报到:科技普惠潮流渐起,“开源”将带我们走向何方?

科技云报到原创。 开源决定软件未来&#xff0c;已成为全球技术和产业创新的主导模式之一。“开源”思想的诞生&#xff0c;可以说是计算机发展史中极具理想主义和浪漫主义色彩的一页&#xff0c;是科技自由与技术极客思想的延伸。 数字化浪潮奔涌&#xff0c;从软件开发的底…...

【论文笔记】On Generative Agents in Recommendation

论文信息 标题&#xff1a; On Generative Agents in Recommendation 会议&#xff1a; SIGIR 24 —— CCF-A 作者&#xff1a; An Zhang, Yuxin Chen, Leheng Sheng 文章链接&#xff1a; On Generative Agents in Recommendation 代码链接&#xff1a; On Generative Agents…...

使用 Spring Boot 和 Canal 实现 MySQL 数据库同步

文章目录 前言一、背景二、Canal 简介三、主库数据库配置1.主库配置2.创建 Canal 用户并授予权限 四.配置 Canal Server1.Canal Server 配置文件2.启动 Canal Server 五.开发 Spring Boot 客户端1. 引入依赖2. 配置 Canal 客户端3. 实现数据同步逻辑 六.启动并测试七.注意事项八…...

vue3 在element-plus表格使用render-header

在vue2中 element表格render-header 源码是有返回h()函数的 在vue3 element-plus 表格源码 render-header函数没有返回h函数了 所以需要用render-header方法中创建虚拟DOM节点的话需要引用h方法 <el-table-column header-align"right" align"right" …...

算法——结合实例了解Minimax算法(极小化极大算法)

计算机科学中最有趣的事情之一就是编写一个人机博弈的程序。有大量的例子&#xff0c;最出名的是编写一个国际象棋的博弈机器。但不管是什么游戏&#xff0c;程序趋向于遵循一个被称为Minimax算法&#xff0c;伴随着各种各样的子算法在一块。本篇将简要介绍 minimax 算法&#…...

使用 DeepSeek 生成商城流程图

步骤 1.下载 mermaid 2.使用 DeepSeek 生成 mermaid 格式 3.复制内容到 4.保存备用。 结束。...

什么是GraphQL?

如果你在寻找漏洞利用方式,请参考下面的文章 GraphQL API 漏洞 |网络安全学院 GitHub - swisskyrepo/PayloadsAllTheThings: A list of useful payloads and bypass for Web Application Security and Pentest/CTF GraphQL 查询&#xff08;Query&#xff09; GraphQL 既不是…...

Spring Boot 的约定优于配置,你的理解是什么?

Spring Boot 的“约定优于配置”&#xff1a;开发效率的革命性提升 在软件开发中&#xff0c;开发者常常需要花费大量时间编写繁琐的配置文件&#xff0c;尤其是在传统的 Java EE 或 Spring 框架中。而 Spring Boot 通过“约定优于配置”&#xff08;Convention Over Configur…...

C#开源大型商城系统之B2B2C+O2O一体化_OctShop

一、应用背景与引言 在当今数字化商业的浪潮中&#xff0c;电子商务平台的构建成为众多企业拓展业务、提升竞争力的关键举措。C# 语言以其强大的功能、高效的性能以及良好的开发框架支持&#xff0c;在商城系统开发领域占据着重要地位。独立开源的大型 C# 商城系统&#xff0c…...

gitte远程仓库修改后,本地没有更新,本地与远程仓库不一致

问题 &#xff1a;gitte远程仓库修改后&#xff0c;本地没有更新&#xff0c;本地与远程仓库不一致 现象&#xff1a; [cxqiZwz9fjj2ssnshikw14avaZ rpc]$ git push Username for https://gitee.com: beihangya Password for https://beihangyagitee.com: To https://gitee.c…...

【对比】Pandas 和 Polars 的区别

Pandas vs Polars 对比表 特性PandasPolars开发语言Python&#xff08;Cython 实现核心部分&#xff09;Rust&#xff08;高性能系统编程语言&#xff09;性能较慢&#xff0c;尤其在大数据集上&#xff08;内存占用高&#xff0c;计算效率低&#xff09;极快&#xff0c;利用…...

el-input无法输入0.0001的小数,自动转换为0在vue3中的bug

今天遇到个bug&#xff0c;el-input中只能输入0.1或者输入0.1再加上00成为0.001&#xff0c;不能直接输入0.001&#xff0c;否则自动转换为0。需要去掉 v-model.number后面的 .number 源代码&#xff1a; <el-table-column label"实发数量" width"120"…...

Ubuntu 下 systemd 介绍

系列文章目录 Linux内核学习 Linux 知识&#xff08;1&#xff09; Linux 知识&#xff08;2&#xff09; WSL Ubuntu QEMU 虚拟机 Linux 调试视频 PCIe 与 USB 的补充知识 vscode 使用说明 树莓派 4B 指南 设备驱动畅想 Linux内核子系统 Linux 文件系统挂载 QEMU 通过网络实现…...

BERT文本分类(PyTorch和Transformers)畅用七个模型架构

&#xff08;PyTorch&#xff09;BERT文本分类&#xff1a;七种模型架构 &#x1f31f; 1. 介绍 使用BERT完成文本分类任务&#xff08;如情感分析&#xff0c;新闻文本分类等等&#xff09;对于NLPer已经是很基础的工作了&#xff01;虽说已迈入LLM时代&#xff0c;但是BERT…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

mongodb源码分析session执行handleRequest命令find过程

mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程&#xff0c;并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令&#xff0c;把数据流转换成Message&#xff0c;状态转变流程是&#xff1a;State::Created 》 St…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...