显存总量看起来充足,推理服务仍可能因找不到合适的连续空闲块而分配失败。解决这类问题,关键不是定时清空所有缓存,而是把推理集群显卡显存碎片监测与回收纳入日常运行流程:先判断碎片发生在哪一层,再按影响程度逐步回收。
先分清“显存不够”和“显存不好分配”
显存使用量只说明已占用多少,不能直接说明剩余空间能否满足一次分配。驱动层工具通常能观察设备总量、已用量和空闲量;但应用的分配器可能把显存切成不同大小的块,并保留空闲块供后续复用。总空闲量较大、可用块却不匹配请求时,就会出现分配失败或频繁扩展显存池的情况。
推理服务中,模型权重通常长期驻留,KV缓存则随并发请求和上下文长度变化。请求长度差异大、批次频繁变化时,分配器需要处理尺寸不同、生命周期不同的内存块,碎片风险随之上升。因此,监测不能只看设备利用率,也要记录应用分配器的统计。
建立能定位问题的监测指标
- 设备层:记录每张卡的总显存、已用和空闲量,并与服务实例、进程及负载变化关联。设备层空闲量适合发现整体压力,不足以单独判定碎片。
- 分配器层:采集已分配量、保留量、空闲块总量、最大可分配空闲块、分配重试和失败次数。不同运行框架的字段名称不同,应以其公开接口为准。
- 业务层:同步记录并发数、批次大小、输入长度分布、KV缓存占用及请求错误。这样才能区分流量突增、缓存增长与碎片恶化。
可用“1-最大可用空闲块÷可回收空闲块总量”估算碎片率,但必须限定在同一显存池、同一分配条件下;若分配器没有提供块级数据,就不要把设备空闲量代入公式。推理集群显卡显存碎片监测应以趋势和分配失败为主,不宜套用跨框架的固定告警阈值。
按风险从低到高分阶段回收
- 优先复用。检查服务是否重复创建张量或缓存,能复用的缓冲区尽量复用;对输入长度差异明显的任务,可评估长度分桶或固定批次上限,减少尺寸频繁变化。代价是调度规则更复杂,桶划分过细也会降低批处理效率。
- 整理应用内空闲块。确认请求已结束、相关张量不再被引用后,再调用所用框架支持的缓存整理或池收缩接口。释放动作可能带来后续重新申请开销,不应在每个请求结束时无条件执行。
- 排空实例后回收显存池。对持续增长且无法由前两步缓解的实例,先停止接收新请求,等待在途任务完成,再释放可释放的缓存并检查显存变化。模型权重和仍被引用的KV缓存不会因为清理空闲块而消失。
- 最后才重建实例。若分配失败持续发生,且实例内部无法恢复,可从负载均衡中摘除实例,待任务排空后重启或替换。该办法恢复边界清晰,但会产生冷启动时间,需预留服务容量并设置并发恢复限制。
把监测结果变成运维动作
落地时先选一类负载,保存设备层、分配器层和请求层的基线;再通过可重复的压测或真实流量回放,比较不同回收动作前后的失败率、分配重试和延迟。告警应组合使用:例如空闲量持续下降,同时最大空闲块变小、分配重试上升,才触发检查;单一碎片率升高不一定代表需要重启。
推理集群显卡显存碎片监测与回收还要设置动作冷却时间,避免多个实例同时整理或重建造成容量骤降。记录每次回收的触发指标、释放结果和恢复耗时,按负载类型调整策略。核心原则是先复用、再整理、后重建,让显存管理既能及时缓解问题,也不因过度回收引入新的延迟。
常见问题
设备显示仍有空闲显存,为什么申请会失败?
空闲总量不代表存在满足请求条件的可用块。还需检查分配器统计、请求尺寸和是否有其他进程占用。
能否定时清空显存缓存?
不建议无条件定时清空。缓存可能用于后续快速复用,频繁释放和重新申请反而增加开销;应在有指标佐证时执行。
重启实例是不是最彻底的办法?
重启通常能重建进程内分配状态,但会造成冷启动并占用调度容量。应先排空请求,并把它作为分阶段回收的最后手段。