接上一篇Docker文章,关于我使用Ascend显卡时的项目复盘

发布时间:2026/8/7 8:51:41
接上一篇Docker文章,关于我使用Ascend显卡时的项目复盘 引言这是在做text2sql的项目时使用了Ascend显卡来跑模型时出现了的问题解决了故此写了篇文章。一.一阶段在把项目转到那台搭载Ascend显卡服务器上的时候其实一开始还是正常的就是要改数据库连接要换成达梦数据库然后还要在dokcer容器里面的vllm部署好我要的模型并启动这个部分的命令我是直接用团队大佬的在原版的基础上修改参数变成我需要的参数修改了模型文件啊端口映射啊这些东西因为说白了我自己也不知道这个命令是咋写出来的这个时候我还不了解dokcer二.二阶段项目移动了之后出现了一个问题可能是之间数据库中的内容比较少换了数据库并填充了内容之后这次居然会出现超上下文长度的问题后来检查出来了是vanna架构里面在训练时塞入数据库表的ddl时要记得分段不然的话在调取的时候会直接把数据库全部的ddl都调出来因为没分段就会当成一句话当作提示词那就会出现超上下文的情况。由于超出上下文了这里其实一开始我没有意识到是全部的ddl都被拉出来了所以一开始我的操作是把上下文的限制从4096调整为8192后来才发现真正的问题是忘记分段了。三.三阶段在调整使用了一段时间后都没有什么问题只是效果不太理想。但是后面同事调测多卡联调就是把多张Ascend显卡一起用具体是多张显卡跑一个模型还是多张显卡跑多个模型这我就不清楚了可能涉及到显卡的数据通信与交互还需要调一些参数吧。反正就是在调试期间我的服务就被关停了嘛然后等调试完后我再去使用就出问题了。反正就是用他们的说法是我的服务测试期间被关了然后只需要再起起来就可以连上但是很明显我去尝试起服务就起了但是实际使用就会出现报错就是没反应。这里就开始出现问题了。由于调试了很久没有反应我就放弃了打算删了重头再来一遍好这就是噩梦的开始了。这里我就直接docker rm -f xxx就把我那个容器删了好先在这里告诉大家不要这么干一定不要这么干在不确定这个容器进程是否结束以及就算结束了反正多查验一下吧确保没有在进行中。为啥因为如果这个容器进程在进行中而直接执行了docker rm -f xxx那么你就会得到一个僵尸进程一个很难查到并且难以结束的僵尸进程至少先docker stop xxx先把你的容器停掉再做删除工作当然了应该还有更合规的操作方式这里自查吧我还不太清楚最合规的操作方式是什么。我为啥这么干因为被要求要演示这个项目了结果连不上模型没法输出调了很久了都没有解决就直接丢给AI让它帮我解决了然后就放空脑袋听凭AI了。为什么会发现这个问题在删除了原本容器有重建容器后代码的前面部分跑起来了但是在提出问题后就出现了报错说什么显存不够我直接懵了之前都没有出现显存不够的情况咋就突然出现了而且还是显存不够这种问题肯定不对劲。为了解决这个问题中间这里就出现了反复删除反复重建容器的过程。然后就出现了新的问题说什么显存存在足够的显存空间但是这些空闲的空间都被分割的比较小而模型的需求是一大块连续的空闲显存空间具体为什么需要的是一大块连续的空闲显存空间我还不清楚但是为什么会被分割的原因貌似就是我不断的删除后又重建的操作所以再次提醒一定要先停掉容器再删除容器。大概的报错有这些Recv failure: Connection reset by peer这是我去联通vllm时的报错(EngineCore pid344) ERROR 08-03 02:38:39 [core.py:1136] raise ValueError( (EngineCore pid344) ERROR 08-03 02:38:39 [core.py:1136] ValueError: Free memory on device (16.58/43.24 GiB) on startup is less than desired GPU memory utilization (0.85, 36.75 GiB). Decrease GPU memory utilization or reduce GPU memory used by other processes.(APIServer pid1) WARNING 08-03 02:40:01 [platform.py:848] Parameter --disable-cascade-attn is a GPU-specific feature. Resetting to False for Ascend. (APIServer pid1) WARNING 08-03 02:40:01 [platform.py:937] Ignored parameter disable_flashinfer_prefill. This is a GPU-specific feature not supported on Ascend. Resetting to False.这是我查询容器日志发现的错误这里面有三个冲突1.空闲的显卡内存 2.显存占用率参数--gpu_memory_utilization 3.模型必须占用的显存空间。暂时还没有搞懂、然后这里AI给出了一个解决方法就是让我杀掉显卡上的全部进程然后我去查进程杀进程但是前面我说了我的进程由于错误操作其实已经变成僵尸进程了所以根本没法查到进程号当时我是不知道的所以无论我怎么杀进程其实都解决不了问题。或者降低显存需求就是把--gpu_memory_utilization参数降低刚好匹配当前的剩余空闲空间此时还有16多个G的显存空间当然了当时我认为减少这个占占用率会让大模型变笨效率变慢所以我就没有使用这个解决方法但其实不会变笨、但效率会变慢。后面我还是查到了僵尸进程然后结束了进程此时我的显存占用都清零了空闲显存空间也恢复到几乎满的左右然后这里我以为都要拯救成功了在重启服务之后日志还是继续报显存不够的问题。然后给出的修改方式是降低显存占用率--gpu_memory_utilization减少并发请求压缩kv缓存占用其实我都不知道KV缓存是什么--max_num_seqs以及减半上下文窗口大幅降低峰值显存需求--max_model_len但是我还是没有选择这种方式因为我还是觉得很奇怪明明显存清空了但是还是会说显存不够的情况。为什么删了容器还存在VLLMEngineCore进程核心原因vLLM使用多进程MP引擎主进程EngineCore子进程执行docker rm -f只干掉了容器bash主进程子VLLM引擎进程脱离容器cgroup变成宿主机僵尸进程依然持有Ascend NPU 现存句柄CANN驱动不会自动回收内存所以npu-smi能看到26G占用。两个关键诱因1.使用bash -lc 嵌套启动vllm,bash作为容器1号进程子进程脱离后无法被容器信号回收2.docker rm -f发送SIGKILL暴力销毁没有给vllm引擎执行资源释放的时间。后面我又根据操作结束进程但是还是报错啊这里就是新的问题总显存43多个G,参数--gpu_memory_utilization 假设为0.8就会要求43*0.8 G的连续整块空闲内存。vLLM启动时会做内存预校验不是简单读取宿主机npu-smi的空闲值而是容器内CANN运行时读取NPU真实连续可用HBM同时自动扣除1.CANN驱动内核常驻缓存2~4GB固定占用宿主机npu-smi不统计这部分2.ACL算子编译临时缓冲区启动编译模型时占用巨大3.内存碎片之前vllm进程残留销毁后显存碎成几百MB小块总空闲有但是无连续大块内存4.Ascend vLLM框架自身运行时常驻内存算子库、调度器宿主机npu-smi proc-mem 只统计用户态业务进程不会统计驱动内核、编译缓存、内存碎片占用所以看起来”空卡“但容器内真实连续大块内存远远不够34G。之前由于反复启停vllm虽然手动kill了VLLMEngine进程但Ascend CANN不会自动回收全部内存块只会释放进程专属内存驱动缓存、编译缓存、碎片永久留存必须重启NPU驱动/服务器才能彻底清空整块HBM其实后面AI给出了要我去重启这个方案包括但不限于物理重启但是我不敢怕把显卡、服务器搞坏了所以后面其实是另一种方式解决的。14B bfloat16 模型在310P的硬性内存需求XiYanSQL-QwenCoder-14B这个就是我用来text2sql的模型 bfloat16 权重本身就要26GB 左右再加上 8192 上下文、4 并发 KV 缓存、算子临时内存总峰值接近 34G。 当前容器内仅 16.58G 连续可用差了一倍0.8 的利用率参数必然校验失败。vLLM启动校验硬性要求--模型权重KV缓存需要一整块不中断的HBM不能碎片化拼接。Ascend CANN采用伙伴内存分配器频繁启停vLLM会把完整HBM切成几百MB、几GB的碎片显存总和看着很大但不存在一整块连续空间直接触发报错。隐形占用npu-smi完全不统计1.CANN驱动内核常驻显存宿主机命令看不到NPU固件、AI Core调度、HBM内存管理内核模块会长期占用3~6GB固定空间这部分不在用户进程统计里npu-smi info -t proc-mem完全不显示直接从连续大块里扣除。2.算子编译永久缓存碎片元凶第一次启动模型时CANN会编译大模型所有算子编译缓存会占大量离散小块哪怕杀掉vLLM进程编译缓存不会自动清空永久留在HBM里制造碎片。3.容器与宿PID隔离的僵尸显存之前docker rm -f暴力杀容器vLLM多进程主进程Engine Core子进程脱离容器PID命名空间宿主机kill -9只能回收一部分显存驱动侧张量缓冲区不会释放碎块永久残留。在经过一些列操作之后问题没有解决反而更加严重了出现了NPU out of memory. Tried to allocate 136.00 MiB这种报错核心问题NPU显存碎片化严重剩余可用显存只剩307MB加载模型权重直接OOM。然后这里被提议不得不进行NPU复位然后就提供了一些NPU信息工作模式等这样防止复位NPU对设备产生影响本来是要执行npu-smi set -t reset -i 6但是我还是有点觉得不对劲不敢直接复位操作就再继续查询了一些NPU的状态就发现总显存使用率很高大量显存被锁定大页内存Hugepages Usage Rate100%大页内存被占满无法释放AI 算力Aicore/Aicpu/Vectorcore全部0%模型没有在做推理计算 → 典型容器异常导致的 NPU 内核僵尸显存 大页内存卡死容器进程看似在运行但模型推理逻辑卡死、仅占用显存不干活。所以就只能先关停容器再删除容器再清楚宿主机Ascend大页共享内存残留解决 Hugepages 100%占满的问题ipcs -m | grep ascend | awk {print $2} | xargs -I {} ipcrm -m {}执行上面的命令后其实就好了我的问题解决了。还有就是提醒反正我是被提醒了一个NPU只部署一个vLLM推理容器绝对不能同时跑两个模型可以不做显存大块分割max_split_size_mb保留按需扩容释放expandable_segments:True避免一次性把整张卡显存直接占死同时保留TORCH_NPU_CACHE_CLEAN_AT_EXIT1这个变量是进程退出主动清缓存门用来防止僵尸显存残留。Q(这是我心里的问题):什么叫大页内存Hugepages Usage Rate这个翻译感觉有问题哈其次为什么执行 ipcs -m | grep ascend | awk {print $2} | xargs -I {} ipcrm -m {}清理了这个大页内存就没有问题了显存就是显存显存碎片化了或者被占满就应该对显存操作为什么会是对大页内存进行清理就好了。A这是AI的解答:一、先纠正名词Hugepages 巨页内存Linux 内核大页内存属于主机系统物理内存 (RAM)不是 NPU 显存翻译没问题行业标准叫法HugePages / 巨页 / 大页内存Linux 操作系统对主机 CPU 内存DDR 内存的内存页管理机制和昇腾 NPU 卡上的 HBM 显存是两块完全独立硬件。 普通 Linux 默认内存页4KB 小页HugePages 常用规格2MB / 1GB 巨页核心原理区别NPU 显存HBM昇腾 Davinci6 板载显存模型权重、KV 缓存、算子临时张量存在这里vLLM-Ascend 直接通过昇腾驱动访问系统 HugePages主机物理内存服务器主板 DDR 内存是CPU 侧操作系统内存。二、为什么昇腾Ascend驱动会大量占用 Linux HugePages昇腾异构计算NPU-CPU 数据交互、HCCL 集合通信、算子主机侧临时缓冲区、DMA 直接内存存取强制依赖大页内存NPU 和 CPU 之间做数据 DMA 拷贝时使用 HugePages 可以大幅减少页表项、降低 TLB 缓存缺失、减少内核态开销提升 NPU 和 CPU 之间传输带宽HCCL昇腾多卡通信库、算子前置 / 后置 CPU 缓存、Runtime 常驻缓冲区都会直接申请系统 HugePagesvLLM-Ascend 推理框架、ATC 算子编译、CANN 运行时都会持续向操作系统申请预留巨页内存。关键痛点HugePages 是内核静态预留内存不会自动释放普通 4KB 小内存进程退出后操作系统自动回收内存。 HugePages 特性一旦被 CANN / 昇腾驱动申请占用容器进程 docker stop、容器销毁、推理服务 kill 之后巨页不会自动还给系统多次启停 vLLM、重启推理容器、异常崩溃后大量 HugePages 变成僵尸共享内存段ipcs -m 可以看到系统可用巨页持续下降使用率拉满。三、为什么 HugePages 打满会导致 NPU 显存报错、推理 OOM、启动异常最关键逻辑你疑惑明明是显存问题清主机大页内存就恢复逻辑在这里场景 1CANN Runtime 需要主机巨页做显存交换 / 临时缓存当 NPU 显存紧张、出现显存碎片化时昇腾驱动会利用主机 HugePages 作为 NPU 显存的 Swap 后备、算子 Host 侧临时缓冲。 系统 HugePages 耗尽 → CANN 无法分配主机侧辅助缓存 → NPU 显存分配逻辑直接报错、碎片化急剧恶化、算子创建失败、KV 缓存初始化失败。场景 2容器内 NPU 通信、DMA 通路阻塞HugePages 占满后CPU↔NPU 高速 DMA 通道降级为普通 4KB 小页传输数据拷贝时延暴涨算子调度卡顿运行时出现隐性内存泄漏持续蚕食 NPU 可用显存 最终表现就是明明 NPU 显存数值够但是 vLLM 报显存不足、缓存创建失败重启没用只有删掉残留巨页共享内存才能复位。场景 3Ascend 驱动共享内存僵尸段冲突命令ipcs -m | grep ascend筛选的是昇腾驱动创建的 System V 共享内存段全部依托 HugePages 分配 进程异常退出后共享内存段在内核残留新启动的 vLLM 容器的 CANN Runtime 在初始化时尝试申请同名 / 同地址共享内存旧僵尸段残留导致初始化冲突、Runtime 内存管理错乱直接导致 NPU 显存池划分异常可用 KV 缓存显存被异常挤占。 执行ipcrm -m删除残留共享内存CANN 运行时完全重置显存管理恢复正常。场景 4shm-size 容器共享内存联动你 docker 启动配置了--shm-size20g容器共享内存同样优先使用系统 HugePages。 宿主机巨页耗尽 → 容器 /dev/shm 分配失败 → vLLM 内部进程间通信缓冲区分配失败 → 引擎初始化异常间接影响 NPU 显存调度。四、拆解你这条清理命令作用bashipcs -m | grep ascend | awk {print $2} | xargs -I {} ipcrm -m {}ipcs -m列出系统所有 System V 共享内存段grep ascend过滤所有昇腾 CANN、驱动、推理业务创建的共享内存提取 shmidipcrm -m强制删除内核态残留共享内存释放被长期占用的 HugePages 大页内存。五、长期规避方案不用反复手动清巨页方案 1容器停止时自动清理宿主机 Ascend 共享内存编写 docker 容器停止钩子容器销毁自动执行 ipcrm 清理。方案 2配置 HugePages 按需动态分配CANN 推荐关闭静态固定巨页预留开启透明巨页THP操作系统自动回收bash# 开启系统透明大页 echo always /sys/kernel/mm/transparent_hugepage/enabled echo always /sys/kernel/mm/transparent_hugepage/defrag静态 HugePages 不要配置过大避免无法回收。方案 3推理服务正常优雅停止避免暴力 kill -9暴力杀死 vLLM 进程、docker kill 会导致 CANN 无法执行析构逻辑巨页与共享内存无法释放 正常用docker stop优雅停止容器驱动可以主动释放大部分 HugePages 资源。方案 4定时巡检清理定时脚本检测 HugePages 使用率高于阈值自动清理昇腾残留共享内存。六、总结一句话HugePages 是宿主机 CPU 大页内存是昇腾 CANN 驱动、NPU 通信、显存辅助缓存的底层依赖资源 推理服务异常退出会造成巨页共享内存内核残留无法释放HugePages 耗尽会造成昇腾 Runtime 运行异常、显存管理错乱、假性显存不足 清理ipcs -m里的 ascend 共享内存是清理驱动遗留的巨页内存垃圾让 CANN Runtime 初始化恢复正常NPU 显存分配逻辑回归正常问题直接解决。 它不是直接清理 NPU 显存是修复NPU 驱动运行的主机侧底层环境。