中配GPU集群的算力重生:LLM推理与视频转码混部实战
最近一段时间不少团队都遇到过一个挺尴尬的局面花大价钱搭起来的中配 AI 集群跑 7B、13B 这种量级的模型推理绰绰有余但一旦想训练或微调一个稍微大点的模型显存和算力立刻见底平时没人调用的时候一堆 GPU 就那么空转着电费一分不少。这篇文章想探讨的就是怎么给这类“高不成低不就”的集群找一份长期稳定的新工作本地 LLM 推理服务 视频转码任务混部。先说明我的方案不是什么“终结者”而是给中配集群一个更加务实的定位——不再硬扛大模型预训练而是去承接推理、微调、视频批处理这类更加匹配自身规模的算力任务。下面我会从负载特征、硬件选型、调度配置到完整实战挨个拆开来讲。1. 背景中配集群的尴尬与转机1.1 所谓“中配 AI 集群”到底是什么先明确一下“中配”的判断标准避免大家看完全文还不知道自己的集群算不算中配。本文讨论的集群大致满足以下特征单机配有 4 到 8 张 GPU单卡显存集中在 24GB 左右例如 RTX 3090、RTX 4090 或 A10。没有 InfiniBand 高速互联多为万兆以太网或普通千兆网络。主要任务是跑中小规模模型推理、模型微调、数据预处理偶尔跑大规模训练但常常失败。总显存容量能装下 13B 甚至 70B 量化模型但训练这类模型时要么显存不够要么通信瓶颈明显。如果上述条件命中大半恭喜你这就是典型的中配 AI 集群。这种集群在当前环境里非常常见不少高校实验室、中小型 AI 创业公司、企业内部数据部门都配备着类似规模的 GPU 资源。1.2 为什么说它陷入了“闲置困境”以一张 24GB 显存的 GPU 为例单独看它能做的事情其实不少跑一个 7B 参数的对话模型开启 vLLM 或 TensorRT-LLM 后吞吐量可以稳定在每秒几百到上千 token。同时并发处理多个视频转码任务利用 NVENC 硬件编码器速度远快于 CPU 转码。问题在于大部分中配集群的部署思路仍然是“复制大厂预训练集群”的简化版。管理员习惯把集群当作通用 AI 计算平台所有人都申请整卡资源结果就变成了推理时只需要一部分显存却占用了整张卡。训练任务常常因为显存不足或通信瓶颈失败任务排队但没人能跑完。视频转码、音视频处理这类任务被认为“不属于 AI 集群的职责”被拒之门外。GPU 利用率长期维持在 10% 到 30%剩余算力和显存完全被浪费。换句话说中配集群不是性能不够而是任务模型没设计对。1.3 转机把集群拆成“推理节点 转码节点”后来我们换了一种思路。既然预训练不适合中配集群那就把集群的能力拆开来看中配集群最擅长的是“中等规模的单卡或双卡任务”而不是“多机多卡协作任务”。顺着这个思路本地 LLM 推理和视频转码就成了两个非常理想的落地点。本地 LLM 推理对单卡性能敏感但对多卡通信不敏感。视频转码走的更多是 GPU 上的专用硬件编解码单元与 CUDA 算力互不冲突。推理服务往往白天活跃、晚上空闲转码任务往往是批处理适合在夜间或低峰期运行。两类任务可以共存于同一张 GPU 上只是需要合理的隔离和调度策略。于是原本被视为“鸡肋”的集群被重新定义为“多功能算力平台”。这也是本文的核心价值不换硬件不增加预算仅仅通过任务设计和调度改造让中配集群重新忙碌起来。2. 理解底层算力模型LLM 推理和视频转码到底各吃哪些资源在动手配置之前我们要先搞清楚一个关键问题这两类任务在 GPU 上消耗的资源是完全重合还是可以错开的答案直接影响调度策略。2.1 本地 LLM 推理的资源消耗特征本地部署 LLM无论是通过 vLLM、TGI、llama.cpp 还是 TensorRT-LLM其算力消耗主要集中在以下三个部分资源类别消耗方式说明显存模型权重 KV Cache占用量最大量化可降低权重占用CUDA 核心矩阵乘法、Attention 计算Prefill 阶段算力消耗大内存带宽权重读取输出 token 时受显存带宽限制明显以一个 7B FP16 模型为例模型权重大约占用 14GB 显存。即使输入序列不长KV Cache 也会额外占用 1 到 2GB 显存。如果是 13B 模型FP16 权重大约是 26GB一张 24GB 显卡单卡根本放不下必须用 int8 或 int4 量化。从 CUDA 核心占用上看LLM 推理其实是“稀疏爆发型”任务Prefill 阶段处理输入时算力占用极高但持续时间短。Decode 阶段生成输出时算力占用不高主要瓶颈在显存带宽和 KV Cache 管理。当使用 vLLM 的 Continuous Batching 特性后多个请求可以被拼在一起推理GPU 利用率会显著提升但仍然不是 100% 满载。结论是LLM 推理吃显存但算力利用率可能只有 40% 到 60% 左右存在明显的算力剩余空间。2.2 视频转码的资源消耗特征视频转码是完全不同的模型。FFmpeg 在调用 NVENC / NVDEC 硬件编解码器时编解码工作由 GPU 上独立的硬件单元完成不占用 CUDA 核心。而视频处理中的缩放、滤镜、格式转换等操作则仍然会用到 CUDA 核心或 dedicated 硬件单元。资源类别消耗方式说明NVENC/NVDEC视频编码和解码不同 GPU 支持的并发路数不同显存帧缓冲占用量通常不大几百 MB 到 2GB 左右CUDA 核心缩放、滤镜、像素格式转换取决于是否开启硬件加速滤镜内存带宽帧数据传输高分辨率高帧率时有压力大多数视频转码任务对显存的消耗不大但对硬件的持续稳定性要求较高。4K 视频转码持续几小时是常事对散热、供电都有明显压力。2.3 两类任务为什么可以混部把上面的信息放在同一张表里混部的思路就很清晰了维度LLM 推理视频转码混部空间显存占用高低转码可以利用推理任务剩余显存CUDA 核心中低低硬件编解码器为主资源竞争较小NVENC/NVDEC不使用高频使用完全互补时间特征白天峰值明显适合夜间批处理时间错峰一个比较典型的情况是一张 24GB 显卡上同时跑一个 7B 模型推理服务和一个 1080P 视频转码任务推理服务占用了大约 16GB 显存转码任务占用 1GB 左右显存CUDA 核心偶尔被转码滤镜占用但整体对推理的延迟影响可控。当然这里必须强调一点混部不是“无脑叠加”。如果推理服务是线上业务延迟敏感程度高那就需要通过 GPU 计算能力隔离手段来保证推理服务质量如果推理只是内部测试可以接受偶尔变慢那混部就没有太大压力。3. 方案总体设计重新定义集群的“岗位”理解了底层的资源模型之后下面我们要做的是把集群重新设计成一套“双底座”架构。3.1 总体架构推理优先 转码填缝我的设计思路是把集群中的 GPU 节点划分为两类角色一类是“推理优先节点”另一类是“转码优先节点”。推理优先节点在白天优先保障 LLM 在线服务夜间当负载降低后才允许调度转码任务。转码优先节点则相反默认接收转码批处理任务当推理服务排队严重时可以把部分转码任务挂起或转移到其他节点。调度层统一管理避免人工干预。从架构图上看整个流程如下用户请求 | v API 网关 / 调度器 | -- LLM 推理节点vLLM / TensorRT-LLM | | | -- 白天优先推理晚上接受转码 | -- 视频转码节点FFmpeg NVENC | -- 批处理队列可被抢占3.2 任务优先级设计调度系统需要给任务设置优先级。这里我建议采用一个简单而有效的三层优先级模型优先级任务类型说明P0在线 LLM 推理服务不可抢占必须保证响应延迟P1重要数据批处理转码可以等待但不希望被中断P2普通转码任务可延迟执行可被 P0 抢占实际调度中P0 任务固定保留一部分 GPU 资源P1 和 P2 则利用剩余资源。如果 P0 的请求量激增调度器可以把 P2 转码任务暂停或换机。这样的设计不会让任何一类任务完全阻塞另一类任务同时能在整体上实现“算力闲时回收”。3.3 为什么我选择 Slurm 作为调度底座在调度层我比较推荐 Slurm。原因很简单Slurm 本身支持 GPU 资源管理可以直接感知每张卡的状态。支持节点级、分区级的资源隔离。支持抢占Preemption特性可以让高优先级任务打断低优先级任务。部署和维护比 Kubernetes 简单中配集群普遍能接受。如果你所在团队已经全面上了 Kubernetes也可以参考后文的设计思路实现类似的调度但本文后面的实战部分以 Slurm Shell 脚本为主。4. 环境准备与硬件选型4.1 硬件选型建议这里不推荐唯一的“标准配置”但可以给出一个符合大多数中配集群现状的样板组件建议配置说明GPUNVIDIA RTX 4090 / RTX 3090 / A1024GB 显存级别CPU16 核以上用于数据预处理、文件读写内存64GB 以上转码任务依赖内存做缓冲存储NVMe SSD 或 SSD 阵列转码读写频繁磁盘速度影响明显网络千兆或万兆以太网推理服务需要转码任务对网络要求较低如果你的 GPU 是 A800、H800 这类更高端的型号方案的思路同样适用只是“中配”变成“高配”调度策略中混部的空间会更大。4.2 软件版本说明本文示例的环境如下Ubuntu 20.04 / 22.04其他主流 Linux 发行版也可命令略有差异NVIDIA 驱动版本 535 或更高CUDA 12.2 或更高Python 3.10vLLM 0.4.x 或更新版本推理示例FFmpeg 6.0 或更新版本需启用 NVENC/NVDEC 支持Slurm 23.02 或相近版本如果读者环境中的版本不一致请以自己实际环境为准调整命令示例。重点是理解配置和调度逻辑而不是死记版本号。4.3 准备示例项目结构为了方便后续演示我们建立一个统一的目录结构/opt/ai-cluster/ ├── config/ │ ├── slurm/ │ │ ├── slurm.conf │ │ └── gres.conf │ └── scripts/ │ ├── start_llm.sh │ ├── start_transcode.sh │ ├── submit_transcode.sh │ └── gpu_watch.py ├── models/ │ └── qwen2-7b-instruct/ # 示例模型 ├── videos/ │ ├── input/ # 待转码视频 │ └── output/ # 转码结果 └── logs/ ├── vllm.log └── transcode.log5. 实战搭建“LLM 推理 视频转码”混部集群5.1 配置 Slurm 的 GPU 资源管理首先要在slurm.conf中声明计算节点和分区。以下是一个简化配置假设集群中有两台 GPU 节点节点名称为gpu01和gpu02。/etc/slurm/slurm.conf核心片段# 控制节点和备份控制节点 SlurmctldHostmaster01 # 计算节点 NodeNamegpu01 Gresgpu:8 CPUs64 RealMemory251000 Sockets2 CoresPerSocket32 ThreadsPerCore1 StateUNKNOWN NodeNamegpu02 Gresgpu:8 CPUs64 RealMemory251000 Sockets2 CoresPerSocket32 ThreadsPerCore1 StateUNKNOWN # 分区定义 PartitionNamellm NodesALL DefaultNO MaxTimeINFINITE StateUP PriorityJobFactor50 PartitionNamevideo NodesALL DefaultNO MaxTimeINFINITE StateUP PriorityJobFactor20 PartitionNameinteractive Nodesgpu01 DefaultYES MaxTime12:00:00 StateUP这里的关键点Gresgpu:8表示节点上有 8 张 GPU。PartitionNamellm是推理分区PartitionNamevideo是转码分区。PriorityJobFactor用于控制不同分区任务的优先级。同时需要配置gres.conf告诉 Slurm 每张 GPU 的类型。/etc/slurm/gres.confNodeNamegpu01 Namegpu TypeRTX4090 File/dev/nvidia0 NodeNamegpu01 Namegpu TypeRTX4090 File/dev/nvidia1 NodeNamegpu01 Namegpu TypeRTX4090 File/dev/nvidia2 NodeNamegpu01 Namegpu TypeRTX4090 File/dev/nvidia3 NodeNamegpu01 Namegpu TypeRTX4090 File/dev/nvidia4 NodeNamegpu01 Namegpu TypeRTX4090 File/dev/nvidia5 NodeNamegpu01 Namegpu TypeRTX4090 File/dev/nvidia6 NodeNamegpu01 Namegpu TypeRTX4090 File/dev/nvidia7 NodeNamegpu02 Namegpu TypeRTX4090 File/dev/nvidia0 NodeNamegpu02 Namegpu TypeRTX4090 File/dev/nvidia1 NodeNamegpu02 Namegpu TypeRTX4090 File/dev/nvidia2 NodeNamegpu02 Namegpu TypeRTX4090 File/dev/nvidia3 NodeNamegpu02 Namegpu TypeRTX4090 File/dev/nvidia4 NodeNamegpu02 Namegpu TypeRTX4090 File/dev/nvidia5 NodeNamegpu02 Namegpu TypeRTX4090 File/dev/nvidia6 NodeNamegpu02 Namegpu TypeRTX4090 File/dev/nvidia75.2 启动本地 LLM 推理服务在 GPU 节点上我们用 vLLM 启动一个 7B 模型的 OpenAI 兼容接口。vLLM 的优势是自带 Continuous Batching能提高 GPU 利用率非常适合混部场景。config/scripts/start_llm.sh#!/bin/bash # 启动 vLLM 推理服务 MODEL_PATH/opt/ai-cluster/models/qwen2-7b-instruct GPU_IDS${1:-0,1} python -m vllm.entrypoints.openai.api_server \ --model $MODEL_PATH \ --tensor-parallel-size 2 \ --gpu-memory-utilization 0.7 \ --max-model-len 8192 \ --dtype float16 \ --port 8000 \ --gpu $GPU_IDS解释几个关键参数--gpu-memory-utilization 0.7vLLM 最多使用单卡 70% 的显存剩下的 30% 留给转码任务或其他进程。--tensor-parallel-size 2如果两张卡都用于推理可以把模型拆分在两张卡上。--max-model-len 8192限制最大上下文长度防止 KV Cache 无限增长。注意以上命令中--gpu参数不是 vLLM 的标准参数实际使用时请通过CUDA_VISIBLE_DEVICES控制 GPU 编号。正确写法是#!/bin/bash export CUDA_VISIBLE_DEVICES0,1 python -m vllm.entrypoints.openai.api_server \ --model /opt/ai-cluster/models/qwen2-7b-instruct \ --tensor-parallel-size 2 \ --gpu-memory-utilization 0.7 \ --max-model-len 8192 \ --dtype float16 \ --port 80005.3 编写视频转码脚本视频转码我们使用 FFmpeg 的 NVIDIA 硬件加速能力。一个典型的脚本如下config/scripts/transcode.sh#!/bin/bash # 视频转码脚本利用 NVENC 进行 H.264/H.265 编码 INPUT_FILE$1 OUTPUT_FILE$2 GPU_ID${3:-0} export CUDA_VISIBLE_DEVICES$GPU_ID ffmpeg -y \ -hwaccel cuda \ -hwaccel_output_format cuda \ -i $INPUT_FILE \ -c:v h264_nvenc \ -preset p5 \ -tune hq \ -cq 23 \ -c:a copy \ $OUTPUT_FILE脚本参数说明-hwaccel cuda使用 CUDA 硬件解码。-c:v h264_nvenc使用 NVENC 进行 H.264 编码。-preset p5NVENC 质量与速度的平衡档。-cq 23恒定质量模式下控制画质数值越小画质越好文件越大。-c:a copy音频流直接复制不转码。如果你的输入视频本身是 H.265想转成 H.264可以改为ffmpeg -y \ -hwaccel cuda \ -hwaccel_output_format cuda \ -i $INPUT_FILE \ -c:v h264_nvenc \ -preset p5 \ -cq 23 \ -c:a copy \ $OUTPUT_FILE5.4 通过 Slurm 提交混部任务现在我们要把上述两类任务统一交给 Slurm 管理。提交推理服务任务的脚本config/scripts/submit_llm.sh#!/bin/bash # 向 llm 分区提交推理服务任务 srun \ --partitionllm \ --gresgpu:2 \ --cpus-per-task16 \ --job-namevllm-server \ --timeinfinite \ bash /opt/ai-cluster/config/scripts/start_llm.sh提交转码任务的脚本config/scripts/submit_transcode.sh#!/bin/bash # 向 video 分区提交批量转码任务 for input_file in /opt/ai-cluster/videos/input/*.mp4; do filename$(basename $input_file .mp4) output_file/opt/ai-cluster/videos/output/${filename}_h264.mp4 sbatch \ --partitionvideo \ --gresgpu:1 \ --cpus-per-task4 \ --job-nametranscode \ --output/opt/ai-cluster/logs/transcode_%A_%a.log \ --wrapbash /opt/ai-cluster/config/scripts/transcode.sh $input_file $output_file 0 done通过sbatch提交任务后可以用以下命令查看队列squeue预期输出类似JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON) 1024 video transcode admin R 0:02 1 gpu02 1025 video transcode admin R 0:02 1 gpu02 1026 video transcode admin PD 0:00 1 gpu02 1023 llm vllm-serv admin R 5:00 1 gpu015.5 验证效果同时跑两类任务为了验证混部的效果我们可以在 GPU 节点上实时查看资源占用情况。config/scripts/gpu_watch.py#!/usr/bin/env python3 # 简单 GPU 监控脚本 # 需要安装 pynvml: pip install nvidia-ml-py import time from pynvml import nvmlInit, nvmlDeviceGetHandleByIndex, nvmlDeviceGetMemoryInfo, nvmlDeviceGetUtilizationRates nvmlInit() device_count 8 # 按实际节点 GPU 数量调整 while True: print( * 60) print(f时间: {time.strftime(%Y-%m-%d %H:%M:%S)}) for i in range(device_count): handle nvmlDeviceGetHandleByIndex(i) mem nvmlDeviceGetMemoryInfo(handle) util nvmlDeviceGetUtilizationRates(handle) print(fGPU{i}: 显存 {mem.used / 1024**3:.1f}GB / {mem.total / 1024**3:.1f}GB, 算力 {util.gpu}%, 显存占用率 {util.memory}%) print( * 60) time.sleep(5)运行后如果混部成功你会看到类似这样的输出GPU0: 显存 14.2GB / 23.9GB, 算力 41%, 显存占用率 35% GPU1: 显存 1.1GB / 23.9GB, 算力 63%, 显存占用率 42%其中 GPU0 偏向推理显存占用高但算力中等GPU1 偏向转码显存占用低但编码器持续满负荷工作。这正是我们期望的混部效果。5.6 更稳妥的混部方式拆卡如果你希望更彻底地隔离两类任务避免推理任务被转码任务影响可以考虑“拆卡”方案让一张卡只跑推理另一张卡只跑转码。这种方式虽然会损失部分灵活性但实现简单适合对稳定性要求更高的场景。具体做法就是在 Slurm 提交任务时明确指定 GPU ID# 推理任务使用 0-3 号卡 sbatch --partitionllm --gresgpu:4 --nodelistgpu01 --wrapbash start_llm.sh # 转码任务使用 4-7 号卡 sbatch --partitionvideo --gresgpu:4 --nodelistgpu01 --wrapbash transcode_all.sh这种方式适合初步验证混部能力后续再逐步放开到“同卡混部”。6. 调度策略与负载观测6.1 时间维度调度白天与黑夜的差异化配置中配集群的一个天然优势是负载具有明显的时间周期性。白天大家做实验、调接口推理请求量大晚上实验结束推理负载下降转码任务就能趁虚而入。Slurm 没有内置“按时间自动切换”的机制但我们可以用简单的外部定时脚本实现config/scripts/schedule_change.sh#!/bin/bash # 白天把 video 分区设为 DRAIN晚上恢复 HOUR$(date %H) if [ $HOUR -ge 9 ] [ $HOUR -lt 22 ]; then # 白天禁止新的转码任务进入 scontrol update PartitionNamevideo StateINACTIVE else # 晚上允许转码 scontrol update PartitionNamevideo StateUP fi再把这个脚本放到 cron 里0 * * * * /opt/ai-cluster/config/scripts/schedule_change.sh这种时间调度虽然简单但能有效保证白天推理服务的响应质量。6.2 GPU 利用率的观测与告警混部之后最怕出现的情况是“推理卡顿但不知道为什么”“转码任务悄悄占用整卡显存”。建议至少做到三件事部署类似 nvidia-smi、DCGM 的监控采集按分钟记录每张卡的显存、算力、温度和功耗。在 Grafana 或自建页面上展示“推理独占指标”和“转码混部指标”例如推理 P99 延迟、转码任务平均耗时。设置告警如果推理延迟超过阈值立即暂停 video 分区的新任务并考虑抢占已有转码任务。config/scripts/check_gpu_mem.sh#!/bin/bash # 检测 GPU 可用显存低于 2GB 时输出告警 THRESHOLD2048 # 单位 MiB for i in {0..7}; do FREE_MEM$(nvidia-smi --query-gpumemory.free --formatcsv,noheader,nounits -i $i) if [ $FREE_MEM -lt $THRESHOLD ]; then echo WARNING: GPU$i 可用显存不足: ${FREE_MEM}MiB fi done6.3 任务抢占配置如果你的推理服务是线上业务强烈建议配置 Slurm 的抢占特性让低优先级转码任务在推理高峰时自动让位。在slurm.conf中增加PreemptModepartition_prio同时为 llm 分区设置更高的 Priorityscontrol update PartitionNamellm Priority100 scontrol update PartitionNamevideo Priority10这样新提交的推理任务会排队优先于转码任务并在条件允许时抢占正在运行的转码任务。当然PreemptModepartition_prio要求各分区 Priority 配置正确请根据你的 Slurm 版本查阅对应文档。7. 常见问题与排查思路混部过程中最容易遇到的问题集中在资源竞争、驱动兼容和任务调度三个方向。下面列几个高频问题。问题现象常见原因解决思路推理服务延迟突然大幅上升转码任务占用了大量显存带宽或 CUDA 核心检查nvidia-smi dmon确认转码任务是否会抢占 CUDA 核心为推理节点关闭混部或限制转码并发数转码任务报错Cannot load libnvidia-encode.so.1FFmpeg 编译时未启用 NVENC或者 NVIDIA 驱动版本过旧重新编译 FFmpeg启用--enable-nvenc升级 NVIDIA 驱动运行 ffmpeg -encodersSlurm 提示Unable to allocate resources分区节点被标记为 DRAIN或 GPU 资源被占满使用sinfo检查节点状态scontrol show node gpu01查看 GPU 分配情况vLLM 启动时显存不足模型权重加上 KV Cache 超过剩余显存降低--gpu-memory-utilization或改用 INT4 量化模型视频转码速率极慢在 CPU 上运行软编码而不是调用 NVENC检查转码日志是否出现cuda字样确认-c:v使用的是h264_nvencGPU 显示大量显存被占用但算力为零有进程占用显存但处于休眠状态用nvidia-smi查找占用进程使用fuser -v /dev/nvidia*定位下面单独展开一个比较隐蔽的问题nvidia-smi显示的显存占用正常但推理延迟却不稳定。这种情况通常不是显存不够而是显存带宽被抢占。转码任务的大量帧数据搬运会和 LLM 推理的 KV Cache 读写抢带宽。解决方案是对转码任务限制并发数量例如同一节点最多 2 个转码任务。将转码任务固定到显存带宽占用更小的低分辨率任务上。更极端的做法直接拆卡隔离一张卡只做推理一张卡只做转码。8. 最佳实践与工程建议8.1 显存预留原则对推理节点我强烈建议不要把所有显存都分配给 vLLM。至少预留 10% 到 20% 的显存给系统、其他进程和突发任务。例如一张 24GB 显卡vLLM 的--gpu-memory-utilization建议设置为 0.8 左右预留约 4.8GB。否则一旦转码任务申请了少量显存反而可能导致 OOM触发 CUDA Context 重建推理服务直接中断。8.2 合理分配任务优先级中配集群的性能决定了它不能像大型集群那样“什么任务都能扛”。建议明确以下几点在线推理服务永远高于离线转码任务。转码任务最好以批处理方式提交而不是交互式运行。对于不紧急的转码任务建议设置--qosnormal等低优先级 QoS。任务之间相互隔离不要用全局环境变量控制 GPU 编号而应该让调度器指定CUDA_VISIBLE_DEVICES。8.3 关注散热与功耗混部会提高 GPU 的整体负荷。中配集群常见问题是机房散热能力一般如果长时间让 GPU 满负荷运转很容易出现温度过高导致降频反而性能下降。建议在节点上配置温度监控并设定阈值# 每 5 分钟检查一次温度 */5 * * * * /opt/ai-cluster/config/scripts/check_temp.shcheck_temp.sh#!/bin/bash # 温度检查脚本超过 85 度输出告警 TEMP_LIMIT85 for i in {0..7}; do temp$(nvidia-smi --query-gputemperature.gpu --formatcsv,noheader,nounits -i $i) if [ $temp -gt $TEMP_LIMIT ]; then echo ALERT: GPU$i 温度过高: ${temp}°C fi done8.4 备份与恢复策略视频转码任务一般持有原始素材建议保持以下习惯转码任务在写输出文件时先写临时文件完成后原子改名避免半成品文件被下游读取。FFmpeg 转为批处理任务时可以记录每个视频的处理状态防止任务中途被杀导致无从恢复。对重要的原始视频不要只保存在计算节点本地尽量放到分布式存储或对象存储中。8.5 日志规范混部的任务类型多、生命周期不一致如果没有规范的日志出了问题很难排查。建议统一按以下格式落盘logs/ ├── vllm_YYYYMMDD.log ├── transcode_jobid.log ├── schedule.log └── gpu_monitor.log每次转码任务的输出日志中建议至少包含输入文件路径、输出文件路径。使用的 GPU ID。转码开始时间和耗时。FFmpeg 返回码。最终输出文件大小和编码格式。9. 继续深化从混部到服务化现在集群已经能同时跑 LLM 推理和视频转码了但还只是“两堆任务共享一台机器”。如果要走向更成熟的平台还有几个方向可以继续做。9.1 增加推理服务自动扩缩容用 vLLM 启动的推理服务可以配合请求量指标进行自动扩缩容。请求量高时调度器自动申请更多 GPU 给 llm 分区请求量低时自动释放 GPU 给 video 分区。实现方式可以是用squeue定期统计vllm-server任务的 GPU 占用。用 Prometheus 采集推理服务的请求 QPS。编写一个控制脚本根据 QPS 阈值动态调整 vLLM 的副本数量。9.2 转码任务队列化用sbatch一张一张提交任务虽然可行但不够工程化。更好的做法是引入一个简单的任务队列服务比如直接用 Redis 列表存储待转码文件路径。消费者从 Redis 中取出任务调用 FFmpeg 转码。转码完成后写回状态信息。这样如果某个 GPU 节点故障任务可以被其他节点重新消费不会丢失。9.3 推理与转码的服务化封装更进一步可以把两类能力封装成两个内部 API 服务LLM 服务继续使用 vLLM 的 OpenAI 兼容接口。转码服务自己写一个基于 FastAPI 的转码接口接收视频上传返回转码任务 ID然后回调通知转码完成。这种方式可以让业务方像调用普通 API 一样使用 GPU 算力而不需要关心集群调度细节。10. 结语与动手建议中配 AI 集群其实并没有走到“终结”的那一步。它的价值不在于和大厂训练集群比拼极限算力而是找到适合自己的任务集合。本文的核心实战内容可以归纳成一句线明确任务类型推理 vs 转码 - 识别资源需求 - 用 Slurm 隔离资源 - 用优先级调度实现错峰混部 - 持续监控 GPU 负载并调优。建议你从一个小规模验证开始先不要直接上全集群混部而是选择一台 GPU 节点按本文第 5 节的步骤同时跑一个 vLLM 推理服务和一个 FFmpeg 转码任务观察两者是否互相干扰。确认没问题后再把调度范围扩大到整个集群。如果遇到问题优先翻一下第 7 节的问题排查表如果排查不出来多在nvidia-smi的实时输出和 FFmpeg 日志里找线索。如果这篇文章对你有帮助可以收藏备用。后续如果时间允许我会继续更新有关调度策略调优和转码服务化的实践文章。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →