前言 最近在华为昇腾相关设备接触了MindIE大模型部署,与Nvidia有些区别。
这里以2.3.0版本示例,简单记录一下,并提供可用的一键运行配置文件。
不过大模型请自行在huggingface或魔搭获取。
品牌
管理工具
/dev 设备
英伟达
nvidia-smi
/dev/nvidiaX
华为昇腾
npu-smi
/dev/davinciX
工作目录: /opt/qwen3/
模型目录: /data/models/Qwen3-8B
踩过的坑 容器运行挂载了start.sh以补充镜像缺失的pytorch、protobuf等lib依赖,其原本就打在了镜像中,但是没在环境变量中加载到,导致直接运行会报出依赖未找到的错误;所以可能根据版本不同,环境变量中缺失的依赖也可能不同。
真不知道出镜像的人在干什么
所以,docker-compose内请注意挂载config.json、start.sh启动脚本,以及mindie-service路径的latest和版本号(这里是2.3.0)的config.json均需要挂载,注意config.json的权限需要是640。
并且,设备路径 /dev/davinci 中这里指定了设备1, 请根据现场情况调整。
如果有问题,可把command调整为bash方便exec进容器手动调试mindie-service的运行:
1 2 3 4 5 6 cd /usr/local/Ascend/mindie/latest/mindie-service ldd ./bin/mindieservice_daemon | grep not ./bin/mindieservice_daemon
关于/dev/davinci* 和 npu-smi设备卡号差异 期间遇到一个的问题:我使用ls -l /dev/davinci*显示了设备1和3。
1 2 /dev/ davinci1/dev/ davinci3
于是docker-compose.yaml里挂载了/dev/davinci1,但用npu-smi info看,显存占用却显示在NPU 3上。
另一个模型想换个卡用,挂载了/dev/davinci3,但是报Invalid device ID。
搞来搞去最终还是发现应该挂载设备0和1。
在NVIDIA的世界里,/dev/nvidia0基本就对应nvidia-smi里的GPU 0,简单直接。但在昇腾这里,/dev/davinciX中的数字X,并不直接等于npu-smi info里看到的物理NPU ID。
达芬奇设备的”X”实际上是 **Chip Logic ID**,而物理NPU ID与Logic ID的映射关系,需要通过npu-smi info -m来确认。
如下:
1 2 3 4 5 NPU ID-Chip ID-Chip Logic ID-Chip Name1 0 0 Ascend 910B2 1 1 - Mcu3 0 1 Ascend 910B2 3 1 - Mcu
即:/dev/davinci1中的1是Logic ID,它映射到的是物理NPU 3。
Logic ID 0对应的物理NPU 1,按道理应该是/dev/davinci0,但系统里却没有这个节点,不过又能正常挂载。
映射关系总结:
/dev/davinciX
Chip Logic ID
物理 NPU ID
npu-smi 显示
/dev/davinci0
0
NPU 1
NPU 1 的 HBM 变化
/dev/davinci1
1
NPU 3
NPU 3 的 HBM 变化
关键规则:
/dev/davinciX 的 X = Chip Logic ID ,不是物理 NPU 编号
config.json 中 npuDeviceIds 的值也是 Logic ID
npu-smi info 展示的是物理 NPU ID,和 davinci 设备号没有直接对应关系
在 privileged: true 模式下,docker-compose 的 devices 字段对设备访问无实际隔离作用,但可能影响 Ascend Runtime 的环境变量初始化
实际操作中,先跑 npu-smi info -m 确认 Logic ID 映射,再据此配置 npuDeviceIds 和 docker devices。
Daemon 静默不启动:共享内存残留 这是一个极其隐蔽的坑。现象是:权重 36/36 层全部加载成功
1 Loading selected layers: 100 %|██████████| 36 /36 [00:02<00:00, 16.10layer/s]
容器内~/mindie/log/debug/最新日志输出 model initialized,但 Daemon start success! 永远不出现,端口不监听,无任何报错 ,daemon 进程还活着。
debug 日志只有 System is idle, GC is set to a lower threshold 一直刷。
花了大量时间逐一排除各种可能(换卡、改端口、改 npuDeviceIds、缩小 batch 参数、去掉 host 网络模式),全部无效。
根因 /dev/shm 共享内存残留 + 容器缺少 --init(对应 docker-compose 的 init: true) 。
MindIE 的 LLM engine 和 service 层之间通过 POSIX 共享内存(/dev/shm/psm_*、/dev/shm/sem.*)做进程间通信。当容器异常退出(比如多次调试重启),这些共享内存文件会残留在宿主机上(因为用了 ipc: host)。
新启动的 daemon 进程尝试初始化 IPC 时,发现共享内存段已存在但无法接管,于是静默卡死在 warm-up 阶段 ——不报错、不退出、不监听端口。
同时,没有 init: true(即容器内 PID 1 是 bash/start.sh),daemon 的子工作进程退出后变成僵尸进程,进一步污染状态。
解决方案
docker-compose 加 init: true
start.sh 开头加共享内存清理
手动恢复时先在宿主机执行 rm -f /dev/shm/psm_* /dev/shm/sem.*
调试建议 遇到”权重加载成功但 daemon 不启动”时,按这个顺序排查:
清 /dev/shm — 最常见原因,优先排除
加 init: true — 防止僵尸进程
前台跑 daemon — docker exec 进容器手动执行,看完整 stdout/stderr
开 debug 日志 — MINDIE_LOG_LEVEL=debug + MINDIE_LOG_TO_STDOUT=1
检查版本配套 — 宿主机驱动 vs 容器内 CANN/ATB 版本是否匹配
检查 ldd — ldd ./bin/mindieservice_daemon | grep "not found"
不要一上来就改 npuDeviceIds、调 batch 参数或换卡测试——那些是在模型能跑通之后才需要调的东西。
具体可用配置如下 docker-compose.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 version: '3.8' services: qwen3-8b-mindie: image: swr.cn-south-1.myhuaweicloud.com/ascendhub/mindie:2.3.0-800I-A2-py311-openeuler24.03-lts container_name: qwen3-8b-mindie init: true network_mode: host ipc: host privileged: true devices: - /dev/davinci1 - /dev/davinci_manager - /dev/devmm_svm - /dev/hisi_hdc volumes: - /usr/local/Ascend/driver:/usr/local/Ascend/driver - /usr/local/dcmi:/usr/local/dcmi - /usr/local/bin/npu-smi:/usr/local/bin/npu-smi - /data/models:/data/models - /opt/qwen3/config.json:/usr/local/Ascend/mindie/latest/mindie-service/conf/config.json - /opt/qwen3/config.json:/usr/local/Ascend/mindie/2.3.0/mindie-service/conf/config.json - /opt/qwen3/start.sh:/start.sh environment: - MINDIE_LOG_LEVEL=info - MINDIE_LOG_TO_STDOUT=true stdin_open: true tty: true command: /start.sh
config.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 { "Version" : "1.0.0" , "ServerConfig" : { "ipAddress" : "0.0.0.0" , "managementIpAddress" : "0.0.0.0" , "port" : 1025 , "managementPort" : 1026 , "metricsPort" : 1027 , "allowAllZeroIpListening" : true , "maxLinkNum" : 1000 , "httpsEnabled" : false , "fullTextEnabled" : false , "inferMode" : "standard" , "interCommTLSEnabled" : false , "interCommPort" : 1121 , "openAiSupport" : "vllm" , "tokenTimeout" : 600 , "e2eTimeout" : 600 , "distDPServerEnabled" : false } , "BackendConfig" : { "backendName" : "mindieservice_llm_engine" , "modelInstanceNumber" : 1 , "npuDeviceIds" : [ [ 1 ] ] , "tokenizerProcessNumber" : 8 , "multiNodesInferEnabled" : false , "multiNodesInferPort" : 1120 , "interNodeTLSEnabled" : false , "ModelDeployConfig" : { "maxSeqLen" : 8192 , "maxInputTokenLen" : 7168 , "truncation" : false , "ModelConfig" : [ { "modelInstanceType" : "Standard" , "modelName" : "qwen3-8b" , "modelWeightPath" : "/data/models/Qwen3-8B" , "worldSize" : 1 , "cpuMemSize" : 0 , "npuMemSize" : -1 , "backendType" : "atb" , "trustRemoteCode" : true } ] } , "ScheduleConfig" : { "templateType" : "Standard" , "templateName" : "Standard_LLM" , "cacheBlockSize" : 128 , "maxPrefillBatchSize" : 50 , "maxPrefillTokens" : 8192 , "prefillTimeMsPerReq" : 150 , "prefillPolicyType" : 0 , "decodeTimeMsPerReq" : 50 , "decodePolicyType" : 0 , "maxBatchSize" : 200 , "maxIterTimes" : 512 , "maxPreemptCount" : 0 , "supportSelectBatch" : false , "maxQueueDelayMicroseconds" : 5000 , "maxFirstTokenWaitTime" : 2500 } } , "LogConfig" : { "dynamicLogLevel" : "" , "dynamicLogLevelValidHours" : 2 , "dynamicLogLevelValidTime" : "" } , "EnableDynamicAdjustTimeoutConfig" : false }
start.sh
1 2 3 4 5 6 7 8 9 10 11 12 13 #!/bin/bash rm -f /dev/shm/psm_* /dev/shm/sem.* 2>/dev/nullsource /usr/local/Ascend/mindie/latest/mindie-service/set_env.shexport LD_LIBRARY_PATH=/usr/local/lib64/python3.11/site-packages/torch/lib:/usr/local/Ascend/mindie/2.3.0/mindie-llm/lib/protobuf/:/usr/local/Ascend/mindie/2.3.0/mindie-llm/lib/cares:$LD_LIBRARY_PATH echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH " cd /usr/local/Ascend/mindie/latest/mindie-service ./bin/mindieservice_daemon