
这次我们来看 NVIDIA 在 AI 推理服务化方向上的一个开源编排项目——srt-slurm。简单说它把 Slurm 作业调度能力与 NVIDIA GPU 资源管理结合起来解决的是多节点、多卡集群上大模型推理任务“谁用哪张卡、什么时候启动、服务怎么暴露、资源怎么回收”的问题。如果只是单卡跑一个模型这类编排工具未必用得上。但当集群里有几十张卡、多个用户、多个模型实例同时做推理时靠人工分配 GPU、手动启服务、肉眼盯日志的方式很快就撑不住了。srt-slurm 的核心思路就是把推理服务当成 Slurm 作业来管理用队列、分区、资源限制和作业生命周期来兜住整个推理部署流程。下面我会从项目能力速览、适用场景、环境准备、部署启动、功能验证、Slurm 作业编排、接口调用、资源占用、问题排查和最佳实践几个方向展开。重点关注这套方案能不能落地、硬件前置条件是什么、批量和接口能力怎么接、踩坑点在哪里。1. 核心能力速览能力项说明项目类型NVIDIA 开源的 Slurm 编排推理部署工具集/方案编程与运行依赖Slurm 集群环境、NVIDIA GPU 驱动、NVIDIA Container Toolkit、容器运行时核心功能推理服务作业化、GPU 资源调度、多节点多卡编排、服务生命周期管理、批量推理任务队列推理服务层可配合 NVIDIA Triton Inference Server 使用也可托管自定义推理容器硬件门槛需要具备 NVIDIA GPU 的服务器或集群单节点也可用于验证显存占用取决于实际推理模型、批大小和并发数需按实际测试支持平台主流 Linux 发行版要求可安装 NVIDIA 驱动和 Slurm 的服务器环境启动方式命令行 Slurm 作业脚本提交典型的sbatch/srun工作流是否支持 API推理服务本身通常暴露 HTTP/gRPC 接口调度层不直接提供业务 API是否支持批量任务支持通过 Slurm 作业数组和资源队列实现批量推理适合场景多用户 GPU 集群、模型服务化运维、批量推理任务、推理服务灰度上线从技术定位看srt-slurm 不是像 Triton 那样的推理引擎也不是像 Kubernetes 那样完整的云原生调度平台。它更像是 Slurm 上的一层“推理部署编排壳”把模型容器、GPU 资源、作业生命周期和推理服务暴露方式组合成一套可重复操作的流程。2. 适用场景与使用边界2.1 适合谁用srt-slurm 最直接的受众是已经维护 Slurm 集群的团队。高校实验室、企业内部 AI 平台、智算中心这类环境通常已经有 Slurm 作为调度器但日常使用还是以训练任务为主。当团队开始把模型从训练转向推理服务时会发现 Slurm 原生能力并不直接覆盖“服务常驻”“端口暴露”“健康检查”这些运维需求。srt-slurm 的思路是在不引入 Kubernetes 的背景下把推理服务纳入 Slurm 管理。如果团队已经有以下痛点它值得认真评估推理服务启动靠 ssh 到节点上手动敲命令各管各的没有统一入口。GPU 资源被推理任务占用后训练任务不知道哪些卡被占了。多个用户同时提交推理服务时端口冲突、显存超卖、互相干扰频发。批量推理任务没有队列概念全部塞在一个脚本里失败一次就要重跑全部。2.2 不适合什么场景如果集群规模已经很大需要弹性伸缩、自动扩容、服务发现、滚动更新这些能力srt-slurm 这类基于 Slurm 的方案可能不如 Kubernetes 顺手。Kubernetes 在微服务治理、Ingress 暴露、自动扩缩容、故障自愈方面更成熟但这套方案需要引入额外的云原生基础设施和学习成本。另外如果只是单机单卡跑一个本地演示模型也没必要上 Slurm 编排。先用python app.py和nvidia-smi直接验证模型效果比直接套调度框架效率高得多。2.3 使用边界与合规提醒推理服务一旦涉及人脸图像、语音音色、个人隐私文本、版权素材必须确认数据来源和授权范围。在生产环境部署前建议做好权限隔离和网络访问控制不要让推理接口暴露到公网。批量任务处理用户数据时要加日志审计和脱敏机制。3. 环境准备与前置条件3.1 硬件层面srt-slurm 面向的目标环境是 NVIDIA GPU 集群。单节点也可以验证但完整效果需要至少一个 Slurm 控制节点和一个计算节点。推荐配置角色配置建议控制节点CPU 8 核以上内存 16GB 以上不需要独立 GPU计算节点NVIDIA GPU 一张或多张驱动版本与 CUDA 容器兼容共享存储/home、/data、模型目录建议放在共享存储上网络节点间网络稳定推理服务端口可互通3.2 软件层面需要提前准备的环境包括Linux 操作系统建议 Ubuntu 20.04/22.04 或兼容发行版NVIDIA 驱动驱动版本要支持当前 GPU 型号和 CUDA 容器版本NVIDIA Container Toolkit用于让容器识别和调用 GPUSlurm 工作负载管理器控制节点和计算节点均完成配置Docker 或兼容 OCI 运行时模型文件与推理容器镜像例如 Triton Inference Server 镜像或自定义推理服务镜像3.3 驱动与容器运行时检查在部署 srt-slurm 之前先确认底层 GPU 容器链路是通的。先看驱动nvidia-smi这条命令能显示 GPU 型号、驱动版本和 CUDA 版本。如果命令不存在说明驱动未安装或未正确加载。再看容器是否能访问 GPUdocker run --rm --gpus all nvidia/cuda:12.4.0-base-ubuntu22.04 nvidia-smi如果这条命令能正常输出 GPU 信息说明 NVIDIA Container Toolkit 工作正常。如果报权限错误或找不到 GPU需要先排查驱动和容器工具包。4. 安装部署与启动方式srt-slurm 的部署不是一个单一命令能完成的过程它依赖 Slurm 集群本身先跑通。实际部署时建议按下面的顺序走。4.1 确认 Slurm 集群状态在控制节点上执行sinfo输出中应该能看到分区信息和节点状态。例如PARTITION AVAIL TIMELIMIT NODES STATE NODELIST gpu up infinite 2 idle gpu-node-01,gpu-node-02如果节点不是 idle 而是 down需要先处理节点状态scontrol update NodeNamegpu-node-01 Stateidle4.2 准备推理服务容器镜像编排推理部署通常需要一个包含推理服务的容器镜像。可以基于 NVIDIA Triton Inference Server 官方镜像也可以使用自定义 Python 推理服务镜像。拉取镜像示例docker pull nvcr.io/nvidia/tritonserver:24.05-py3镜像拉取后先在当前节点做一次手动启动验证确认推理服务能正常加载模型docker run --rm --gpus all \ -p 8000:8000 -p 8001:8001 -p 8002:8002 \ -v /data/models:/models \ nvcr.io/nvidia/tritonserver:24.05-py3 \ tritonserver --model-repository/models注意具体镜像标签和模型目录需要根据实际项目情况调整。这一步的目的是验证镜像本身没问题再去接 Slurm。4.3 编写 Slurm 作业脚本推理服务在 Slurm 上通常使用srun或sbatch启动。下面是一个最基本的推理服务作业脚本模板。#!/bin/bash #SBATCH --job-nametriton-inference #SBATCH --partitiongpu #SBATCH --gresgpu:1 #SBATCH --nodes1 #SBATCH --ntasks-per-node1 #SBATCH --cpus-per-task8 #SBATCH --mem32G #SBATCH --time24:00:00 #SBATCH --output/data/logs/triton-%j.log #SBATCH --error/data/logs/triton-%j.err export NVIDIA_VISIBLE_DEVICES$CUDA_VISIBLE_DEVICES docker run --rm --gpus all \ --shm-size2g \ -p 8000:8000 \ -p 8001:8001 \ -p 8002:8002 \ -v /data/models:/models \ nvcr.io/nvidia/tritonserver:24.05-py3 \ tritonserver --model-repository/models提交作业sbatch run_inference.sh查看作业状态squeue如果作业处于 RUNNING 状态查看日志cat /data/logs/triton-job_id.log4.4 端口冲突处理多个推理服务同时运行时固定端口很容易冲突。两种常见处理方式第一种通过环境变量为每个作业分配不同端口PORT_BASE$((8000 SLURM_JOB_ID % 100))第二种使用--gpus和--gres约束每个作业使用的 GPU 资源并在容器内只利用CUDA_VISIBLE_DEVICES指定的显卡避免显存互相抢占。5. 功能测试与效果验证部署完成后需要分步骤验证整个链路是否可用。下面给出一套通用测试流程。5.1 验证作业调度先提交一个简单的 GPU 探测作业确认 Slurm 能正确分配 GPUsrun --partitiongpu --gresgpu:1 nvidia-smi预期输出是当前计算节点的 GPU 信息。如果这里就失败后续推理服务基本跑不起来。5.2 验证推理服务启动提交推理服务作业后等待服务进入 READY 状态。如果使用 Triton可以查看日志中的模型加载结果。在日志中看到类似下面的内容表示推理服务已就绪Started HTTPService at 0.0.0.0:8000 Started GRPCInferenceService at 0.0.0.0:8001 Started Metrics Service at 0.0.0.0:80025.3 验证推理接口使用 curl 访问 Triton 的模型状态接口curl http://计算节点IP:8000/v2/health/ready如果模型仓库配置正确返回true。查询模型列表curl http://计算节点IP:8000/v2/models5.4 验证批量推理任务在单个节点上验证批量推理有两种方式。方式一通过 Slurm 作业数组每个子任务处理一个数据分片。#!/bin/bash #SBATCH --array1-10 #SBATCH --gresgpu:1 #SBATCH --output/data/logs/batch-%A-%a.log python infer.py --input /data/shard_${SLURM_ARRAY_TASK_ID}.json \ --output /data/result_${SLURM_ARRAY_TASK_ID}.json方式二推理服务启动后通过 HTTP/gRPC 批量请求。这里需要确认推理服务本身支持批量接口。import requests url http://计算节点IP:8000/v2/models/your_model/infer payload { inputs: [ { name: input, shape: [4, 128], datatype: FP32, data: [[0.1] * 128 for _ in range(4)] } ] } response requests.post(url, jsonpayload, timeout30) print(response.status_code) print(response.json())6. Slurm 作业编排与批量任务设计6.1 用 QoS 和分区控制资源推理服务是常驻服务训练任务是短时或周期性任务两者混跑时需要明确资源边界。Slurm 的 QoS 可以做等级和资源限制。例如给推理服务划分一个单独分区只允许该分区内的作业申请 GPUscontrol create PartitionNameinference \ Nodesgpu-node-01,gpu-node-02 \ DefaultYES \ MaxTimeINFINITE \ StateUP用户提交推理作业时指定分区sbatch --partitioninference run_inference.sh6.2 服务化常驻作业推理服务通常需要长时间运行不能像训练任务那样跑完就退出。在 Slurm 上实现服务化核心是让容器进程在前台运行不退出外部通过固定端口访问。作业脚本中需要注意不要使用--nodelist固定单节点避免节点故障时服务无法迁移。使用srun时加--overlap需谨慎容易造成资源超卖。设置合理的--time并在作业接近超时前手动续期或者配合系统策略做作业重启。作业失败后要让 Slurm 自动重排队可以使用--requeue参数。6.3 批量任务队列设计批量推理任务建议把“任务输入”和“执行逻辑”分离。输入数据放到共享目录按分片组织/data/batch_input/ shard_001.json shard_002.json ...批量推理脚本读取指定分片把结果写入输出目录。这样一旦某个分片失败只需要重跑对应的作业数组下标不需要整个任务重跑。#!/bin/bash #SBATCH --array1-10 #SBATCH --partitioninference #SBATCH --gresgpu:1 #SBATCH --output/data/logs/batch_%A_%a.log #SBATCH --error/data/logs/batch_%A_%a.err INPUT_FILE/data/batch_input/shard_${SLURM_ARRAY_TASK_ID}.json OUTPUT_FILE/data/batch_output/result_${SLURM_ARRAY_TASK_ID}.json python batch_infer.py --input $INPUT_FILE --output $OUTPUT_FILE批量任务的状态检查sacct -j job_id --formatJobID,JobName,State,Elapsed,ExitCode6.4 失败重试与日志批量任务失败通常有几个原因数据格式异常、GPU 显存不足、推理服务超时。建议在每个分片脚本里加失败重试逻辑for attempt in 1 2 3; do python batch_infer.py --input $INPUT_FILE --output $OUTPUT_FILE if [ $? -eq 0 ]; then break fi sleep 10 done日志按作业 ID 和任务 ID 分开写便于排查/data/logs/batch_{job_id}_{task_id}.log7. 资源占用与性能观察7.1 实时观察 GPU 占用在计算节点上执行nvidia-smi可以查看当前 GPU 的显存占用和利用率。观察要点显存占用是否接近模型需要的最低值。利用率是否长期处于低值。如果利用率低但显存占用高可能是推理请求并发不够或模型没有开启动态批处理。是否存在多个容器抢占同一张 GPU 的情况看nvidia-smi里多个进程是否同时绑定同一张卡。7.2 从 Slurm 查看历史资源记录作业结束后用sacct查看资源使用sacct -j job_id --formatJobID,JobName,State,Elapsed,NodeList,NTasks,AllocGRES查看 GPU 利用率需要配合nvidia-smi或 DCGM 监控。如果在容器内启用 DCGM可以通过 Prometheus 拉取指标做长期趋势观察。7.3 影响性能的关键参数推理服务的资源占用受几个参数影响最大模型精度FP16、INT8 通常比 FP32 显存占用低。批大小批大小越大GPU 利用率越高但显存占用也越高。并发请求数并发过高会导致排队和显存压力增加。输入序列长度大模型推理时序列长度对显存影响非常明显。动态批处理开启动态批处理后适合压榨 GPU 利用率但要控制最大批大小。7.4 降低显存占用的思路优先使用量化版本模型。关闭多余的计算流。控制推理并发数。使用 Triton 的模型并发配置设置instance_group数量。在 Slurm 作业中限制 GPU 数量避免单卡塞太多实例导致 OOM。8. 常见问题与排查方法问题现象可能原因排查方式解决方案作业一直处于 PENDING分区资源不足或 QoS 限制squeue -j job_id查看原因scontrol show job job_id释放资源、调整分区、检查 QoS容器启动失败提示找不到 GPUNVIDIA Container Toolkit 未安装docker run --rm --gpus all nvidia/cuda:xxx nvidia-smi安装或重装 NVIDIA Container Toolkit推理服务端口无法访问端口被占用或作业节点不在当前网段登录计算节点执行ss -lntp检查监听端口换端口或调整网络访问策略显存不足导致容器退出模型超出单卡显存查看日志中的 CUDA OOM 信息使用量化模型、减小批大小、增加--mem无有效作用应调整 GPU 数量多个作业端口冲突所有作业都固定同一个端口检查日志中的端口绑定错误通过环境变量动态分配端口批量任务某个分片失败数据格式异常或输入超长查看对应分片的日志定位具体数据增加数据校验和失败重试作业运行一段时间后被终止Slurm 的--time超时sacct查看作业运行时间重新提交并延长--time模型加载慢或卡住模型文件存储在非共享存储节点间需要拷贝查看日志中的加载耗时将模型目录放到共享存储CPU 使用率过高数据预处理或后处理太耗时使用top或容器内pidstat查看进程把预处理放到 GPU 加速流程中推理结果不稳定模型未固定随机种子或输入顺序变化对比多次输出固定随机种子稳定输入顺序9. 最佳实践与使用建议9.1 先做最小可运行验证不要一上来就在生产集群上铺开部署。先在一台计算节点上完成“提交作业 - 启动容器 - 调用接口 - 关闭作业”的最小闭环确认整个链路通畅后再扩展节点。这能减少后续排查问题的干扰面。9.2 把模型、数据、日志分目录管理推荐目录结构/data/inference/ models/ # 模型仓库只读 inputs/ # 批量输入数据 outputs/ # 批量输出结果 logs/ # 推理服务日志 scripts/ # 作业脚本和工具脚本模型目录只读输出目录按日期或批次单独建目录日志按作业 ID 命名。这样不管是人工排查还是写脚本清理过期文件都省事。9.3 批量任务要做断点续跑批量推理场景中一次性跑大量数据几乎必然遇到个别数据异常。建议在任务设计阶段就支持分片重跑而不是把整个任务粘合成一个进程。数据分片、输出幂等、失败重试这三件事做好批量任务基本不会崩溃。9.4 服务接口要做访问控制推理服务一旦接进集群网络就要考虑访问范围。建议服务只监听内网 IP。通过防火墙或安全组限制访问来源。如果服务需要暴露给外部前面加一层鉴权代理。涉及敏感数据的接口必须有调用方身份记录。9.5 注意合规与授权凡是用到人脸、声音、版权素材、个人数据推理的场景都要先确认授权。批量处理数据前检查数据来源和用途。商业化使用模型前核实模型开源协议和训练数据版权。10. 总结与下一步srt-slurm 这类方案的核心价值不是替代推理引擎而是把推理服务从“手工启动进程”升级成“集群调度作业”。在已有 Slurm 的环境中它能用最低的改动成本把 GPU 资源、模型容器和批量任务统一管起来。最先应该验证的是三件事Slurm 作业能否正确分配 GPU、推理容器能否在作业中正常启动和响应请求、批量任务能否分片执行并在失败后重跑。这三个闭环跑通整套方案就基本可用了。最容易踩的坑集中在两块一是底层 GPU 容器链路没打通就急着部署导致作业虽然起来了但容器访问不了 GPU二是端口和资源冲突没有在设计阶段考虑多个服务同时启动后相互干扰。这两类问题都能通过先做单节点最小验证来规避。后续可以从三个方向继续扩展接入 Prometheus 和 DCGM 做推理服务监控使用多模型仓库增强单节点服务密度以及配置自动重排队和作业依赖策略让推理服务更接近生产级运维水平。建议把这篇作为起步参考实际部署时以 NVIDIA 官方项目文档和你的集群配置为准。用最小环境跑通一遍再逐步加上多节点、多模型和批量队列比直接照搬大集群方案更稳。