Skip to main content

大规模AI大模型的训练和微调已成为当今人工智能领域的核心工程挑战。训练一个百亿参数的模型往往需要数百乃至数千块GPU协同运行数天。在这一背景下,如何高效地管理GPU集群、调度训练作业、最大化算力利用率,成为AI基础设施团队必须面对的关键问题。

本文将系统介绍高性能计算(HPC)的基本概念与技术体系,并重点深入讲解Slurm工作负载管理器在AI大模型训练和微调场景中的架构、使用方法与实践经验。

什么是高性能计算

高性能计算(High-Performance Computing,简称HPC)是指利用大量互联的计算节点并行处理极其复杂的计算任务,以达到单台普通计算机无法实现的计算性能。其核心目标是在可接受的时间内完成需要巨大计算量的科学、工程或数据分析任务。

HPC解决的核心问题

问题类型典型场景痛点描述
算力瓶颈大模型预训练单节点显存和算力不足以容纳千亿参数模型
时间约束科学计算、气象模拟单机完成需数年,并行后缩短至数小时
数据规模基因测序、天文数据分析数据量超过单节点处理能力
资源利用多团队共享集群缺乏统一调度导致资源闲置或冲突

常见的HPC技术方案

并行计算模型

  • 共享内存并行(SMP:多核CPU共享内存,通过OpenMP等实现线程级并行,适合单节点内部并行
  • 分布式内存并行(MPI:多节点各自拥有独立内存,通过MPI库在节点间传递消息,是集群计算的主流方案
  • GPU加速计算(GPGPU:利用NVIDIA CUDAAMD ROCm将大量计算密集型任务卸载到GPU,尤其适合矩阵运算
  • 混合并行:结合MPI + OpenMP + GPU,实现多级并行,最大化硬件利用率

高速互联网络

HPC集群的性能瓶颈之一在于节点间通信。常用的高速互联技术包括:

技术带宽延迟特点
InfiniBand200Gb/s+< 1μs超低延迟,专为HPC设计
RoCE100Gb/s+1-5μs基于以太网的RDMA,成本较低
NVLink600GB/s+极低NVIDIA GPU间直连,单机内部
GPUDirect RDMA100Gb/s+< 2μsGPU直接与网卡通信,绕过CPU

资源管理与作业调度

在多用户、多任务的集群环境中,需要一套资源管理系统来统一调度和管理计算资源。主流的HPC资源管理系统包括:

系统开发方特点
SlurmSchedMD开源,主流HPC集群首选,支持GPU调度
PBS/TorqueAltair商业版PBS Pro,历史悠久
LSFIBM商业系统,功能完善,企业级支持
SGE/UGEOracle/Altair网格引擎,多适用于生物信息学
KubernetesCNCF云原生容器编排,AI推理场景强

HPC在AI大模型训练与微调中的应用

为什么AI大模型训练必须依赖HPC

现代AI大模型的规模已远超单节点算力边界:

  • GPT-3(175B参数):需要数百块A100 GPU运行数周才能完成训练
  • LLaMA-3(70B参数):微调一次完整模型需要至少8块80GB A100
  • Mixtral-8x7B:混合专家模型需要跨节点的精细资源调度

这些规模决定了AI训练必须在多节点GPU集群上运行,也就是必须依赖HPC基础设施。

AI训练中的并行策略与HPC的对应关系

HPC在AI微调场景中的价值

应用场景HPC必要性核心需求
全参数微调(Full Fine-tuning高,模型需完整加载多卡显存聚合、梯度同步
LoRA/QLoRA微调中,显存需求降低快速任务调度、队列管理
持续预训练高,时间长、规模大作业检查点、故障恢复
强化学习微调(RLHF高,需要多组件协同Actor/Critic分离部署
批量评估推理中,并发任务多多任务队列、资源公平分配

什么是Slurm

SlurmSimple Linux Utility for Resource Management)是一个开源的、容错性强、高度可扩展的集群管理和作业调度系统,广泛应用于全球顶级超算中心和大型GPU训练集群。它由SchedMD公司主导开发和维护,遵循Apache 2.0开源协议。

Slurm承担三个核心职责:

  1. 资源分配:将计算节点(含CPU、内存、GPU等)独占或非独占地分配给用户指定时长
  2. 作业管理:在分配的节点上启动、执行和监控并行作业
  3. 队列仲裁:管理待执行作业的队列,按优先级和策略调度

Slurm的显著优点

优点说明
开源免费无商业授权费用,社区活跃,持续迭代
原生GPU支持通过GRES机制精细管理GPU资源,支持MIG、MPS
高可用支持备用控制节点,单点故障自动切换
丰富的调度策略多因子优先级、公平调度、抢占调度、回填调度
计量记账完整的作业历史记录和资源使用统计
可扩展插件覆盖认证、调度、记账、MPI等各类插件接口
广泛的生态支持与PyTorch、DeepSpeed、MPI等深度集成
大规模验证全球Top500超算榜单中绝大多数使用Slurm

Slurm与Kubernetes的对比

AI训练场景下,SlurmKubernetes各有侧重:

维度SlurmKubernetes
设计定位HPC作业批量调度容器化服务编排
GPU调度原生支持,精细到设备级需要Device Plugin,粒度较粗
训练适合性非常适合批处理训练任务适合推理服务,训练需额外框架
启动速度秒级(无容器开销)分钟级(镜像拉取、容器启动)
故障恢复节点级,作业重排队Pod重启,需配合Checkpoint
多租户隔离账号/分区体系成熟Namespace隔离,RBAC
学习曲线对HPC工程师友好对云原生工程师友好
在线推理不适合非常适合

在实践中,许多大型AI团队采用混合架构:Slurm负责训练,Kubernetes负责推理服务,二者各司其职。

Slurm的架构设计

整体架构

核心组件详解

slurmctld — 主控制守护进程

slurmctldSlurm的"大脑",运行在管理节点(headnode)上,负责:

  • 监控所有计算节点的状态(在线、下线、故障等)
  • 接收用户提交的作业请求
  • 根据调度策略决定作业在哪些节点上运行
  • slurmd下发作业执行指令

为保证高可用,slurmctld支持配置备用节点,主节点故障时备用节点自动接管。

slurmd — 计算节点守护进程

slurmd运行在每一个计算节点上,是"工人"角色,负责:

  • slurmctld上报本节点的资源信息(CPU数量、内存大小、GPU数量等)
  • 接收slurmctld下发的作业步骤(job step
  • 启动、监控和清理作业进程
  • 收集作业资源使用数据

slurmdbd — 数据库守护进程

slurmdbd是可选组件,负责将作业的历史记录、用户账号、资源使用统计等数据持久化到MySQL/MariaDB数据库中,支持:

  • 跨集群的统一记账
  • 作业历史查询(sacct命令)
  • 基于账号的资源限额管理(QOSlimits

slurmrestd — REST API守护进程

slurmrestd是可选的REST API服务,允许外部系统(如AI平台、工作流引擎)通过标准HTTP API提交作业、查询状态,而无需安装Slurm客户端工具。这在与KubernetesAirflow等系统集成时非常有用。

Slurm的核心概念

概念说明
Node(节点)集群中的单台计算服务器,可包含多个CPU核和GPU
Partition(分区)节点的逻辑分组,类似于作业队列,可设置不同的策略
Job(作业)用户提交的计算任务,包含资源需求和执行脚本
Job Step(作业步骤)作业内部的并行子任务,通过srun启动
GRES(通用资源)GPU等特殊资源的抽象,支持精细的资源调度
QOS(服务质量)作业优先级和资源限额的策略集合
Account(账号)用户组织单元,用于记账和资源配额管理

Slurm的使用与配置

安装与基础配置

Slurm的核心配置文件为/etc/slurm/slurm.conf。以下是一个适合GPU训练集群的配置示例:

# /etc/slurm/slurm.conf 基础配置示例

# ==================== 全局配置 ====================
ClusterName=ai-gpu-cluster
SlurmctldHost=headnode01 # 主控节点
SlurmctldHost=headnode02 # 备用控制节点(可选)

# 认证
AuthType=auth/munge

# 调度器设置
SchedulerType=sched/backfill # 开启回填调度,提升利用率
SelectType=select/cons_tres # 消耗型资源分配(GPU调度必须)
SelectTypeParameters=CR_Core_Memory

# ==================== 资源类型配置 ====================
# 注册GPU为可调度资源
GresTypes=gpu

# ==================== 记账配置(需slurmdbd)====================
AccountingStorageType=accounting_storage/slurmdbd
AccountingStorageHost=headnode01
AccountingStorageTRES=gres/gpu # 统计GPU使用量

# ==================== 节点配置 ====================
# GPU训练节点:每节点8块A100 80GB
NodeName=gpu-node[01-16] \
CPUs=128 \
RealMemory=1048576 \
Gres=gpu:a100:8 \
State=UNKNOWN

# ==================== 分区配置 ====================
# 普通训练分区
PartitionName=train \
Nodes=gpu-node[01-08] \
Default=YES \
MaxTime=72:00:00 \
State=UP

# 高优先级分区(长时间训练)
PartitionName=train-priority \
Nodes=gpu-node[09-16] \
MaxTime=7-00:00:00 \
AllowGroups=ml-team \
State=UP

GPU资源配置(gres.conf)

gres.conf描述每个计算节点上的GPU详细信息:

# /etc/slurm/gres.conf
# 自动检测NVIDIA GPU(推荐)
AutoDetect=nvml

# 若需手动指定,示例如下(8卡A100节点):
# Name=gpu Type=a100 File=/dev/nvidia[0-7]

常用命令速查

命令用途常用示例
sbatch提交批量作业sbatch train.sh
srun交互式运行或启动作业步骤srun --gres=gpu:4 python train.py
squeue查看作业队列squeue -u $USER
sinfo查看节点和分区状态sinfo -o "%N %G %T"
sacct查询作业历史记录sacct -j 12345 --format=JobID,State,Elapsed
scancel取消作业scancel 12345
scontrol查看或修改作业/节点状态scontrol show job 12345
sacctmgr管理用户、账号、QOSsacctmgr show user

使用示例一:提交单节点GPU训练作业

以下是一个完整的PyTorch单节点多卡训练作业脚本:

#!/bin/bash
#SBATCH --job-name=llm-finetune # 作业名称
#SBATCH --partition=train # 目标分区
#SBATCH --nodes=1 # 节点数量
#SBATCH --ntasks-per-node=1 # 每节点任务数
#SBATCH --gres=gpu:a100:8 # 请求8块A100 GPU
#SBATCH --cpus-per-task=32 # 每任务CPU数
#SBATCH --mem=256G # 内存需求
#SBATCH --time=24:00:00 # 最长运行时间
#SBATCH --output=logs/finetune_%j.out # 标准输出
#SBATCH --error=logs/finetune_%j.err # 错误输出

# 加载环境
module load cuda/12.2 python/3.10

# 激活虚拟环境
source /path/to/venv/bin/activate

# 设置分布式训练环境变量
export MASTER_ADDR=$(hostname)
export MASTER_PORT=29500

# 使用torchrun启动8卡分布式训练
torchrun \
--nproc_per_node=8 \
--master_addr=$MASTER_ADDR \
--master_port=$MASTER_PORT \
finetune_llm.py \
--model_name meta-llama/Llama-3-70b \
--data_path /data/training_data \
--output_dir /output/checkpoints \
--epochs 3 \
--batch_size 4 \
--lr 2e-4

提交作业:

sbatch train_job.sh

使用示例二:多节点分布式训练(多机多卡)

大模型全参数预训练通常需要多个节点。以下示例展示4节点×8卡(共32块A100)的DeepSpeed训练配置:

#!/bin/bash
#SBATCH --job-name=llm-pretrain
#SBATCH --partition=train
#SBATCH --nodes=4 # 4个计算节点
#SBATCH --ntasks-per-node=8 # 每节点8个进程(对应8块GPU)
#SBATCH --gres=gpu:a100:8
#SBATCH --cpus-per-task=8
#SBATCH --mem=512G
#SBATCH --time=7-00:00:00 # 7天
#SBATCH --output=logs/pretrain_%j.out
#SBATCH --error=logs/pretrain_%j.err

# Slurm自动提供节点列表
MASTER_NODE=$(scontrol show hostnames "$SLURM_JOB_NODELIST" | head -n 1)
MASTER_PORT=29500

echo "Master node: $MASTER_NODE"
echo "All nodes: $SLURM_JOB_NODELIST"
echo "Total GPUs: $((SLURM_NNODES * 8))"

# 使用srun在所有分配节点上启动训练进程
srun \
--nodes=$SLURM_NNODES \
--ntasks=$SLURM_NTASKS \
python -m deepspeed.launcher.launch \
--node_rank=$SLURM_NODEID \
--master_addr=$MASTER_NODE \
--master_port=$MASTER_PORT \
pretrain_gpt.py \
--deepspeed ds_config_zero3.json \
--model_config configs/7b_model.json \
--data_path /data/pile_dataset \
--save_dir /checkpoints/gpt-7b

使用示例三:数组作业(批量超参数搜索)

超参数搜索时,可使用Slurm作业数组同时提交多个作业:

#!/bin/bash
#SBATCH --job-name=hparam-search
#SBATCH --partition=train
#SBATCH --array=0-15 # 提交16个作业,ID为0-15
#SBATCH --nodes=1
#SBATCH --gres=gpu:a100:2 # 每个作业使用2块GPU
#SBATCH --mem=64G
#SBATCH --time=8:00:00
#SBATCH --output=logs/hparam_%A_%a.out

# 定义超参数组合
LEARNING_RATES=(1e-5 2e-5 5e-5 1e-4)
BATCH_SIZES=(8 16 32 64)

LR_IDX=$((SLURM_ARRAY_TASK_ID / 4))
BS_IDX=$((SLURM_ARRAY_TASK_ID % 4))

LR=${LEARNING_RATES[$LR_IDX]}
BS=${BATCH_SIZES[$BS_IDX]}

echo "Task $SLURM_ARRAY_TASK_ID: lr=$LR, batch_size=$BS"

torchrun \
--nproc_per_node=2 \
finetune.py \
--learning_rate $LR \
--batch_size $BS \
--output_dir /output/hparam_lr${LR}_bs${BS}

使用示例四:查询和监控作业状态

# 查看自己的所有作业
squeue -u $USER --format="%.18i %.9P %.30j %.8u %.8T %.10M %.9l %.6D %R"

# 查看GPU节点状态
sinfo -N -p train --format="%.10N %.4c %.8m %.20G %.8t"

# 查看已完成作业的GPU使用情况
sacct -j 12345 --format=JobID,State,Elapsed,AllocTRES%50,MaxRSS

# 实时查看作业输出
tail -f logs/pretrain_12345.out

# 取消特定作业
scancel 12345

# 取消自己所有待运行的作业
scancel --state=PENDING --user=$USER

# 查看集群整体GPU使用情况
sinfo -O NodeList:20,Gres:30,GresUsed:30,State:10

高级配置:服务质量(QOS)管理

在多团队共享GPU集群时,QOS可以实现优先级控制和资源限额:

# 创建普通训练QOS
sacctmgr add qos normal-train \
Priority=10 \
MaxTRESPerUser=gres/gpu=32 \
MaxJobsPerUser=10

# 创建高优先级QOS(用于紧急训练任务)
sacctmgr add qos priority-train \
Priority=100 \
MaxTRESPerUser=gres/gpu=64 \
MaxWallDurationPerJob=7-00:00:00

# 为用户分配QOS
sacctmgr modify user alice set qos=normal-train,priority-train

# 提交作业时指定QOS
sbatch --qos=priority-train train_urgent.sh

与深度学习框架的集成

集成PyTorch分布式训练

Slurm通过环境变量与PyTorch的分布式训练无缝集成:

import os
import torch
import torch.distributed as dist

def init_distributed():
"""从Slurm环境变量初始化分布式训练"""
# Slurm设置的环境变量
rank = int(os.environ.get("SLURM_PROCID", 0))
world_size = int(os.environ.get("SLURM_NTASKS", 1))
local_rank = int(os.environ.get("SLURM_LOCALID", 0))

master_addr = os.environ.get("MASTER_ADDR", "localhost")
master_port = os.environ.get("MASTER_PORT", "29500")

dist.init_process_group(
backend="nccl",
init_method=f"tcp://{master_addr}:{master_port}",
world_size=world_size,
rank=rank
)

torch.cuda.set_device(local_rank)
return rank, world_size, local_rank

集成DeepSpeed

DeepSpeed提供了对Slurm的原生支持,使用deepspeed命令时传入--hostfile参数可自动读取Slurm分配的节点:

# 生成DeepSpeed使用的hostfile
scontrol show hostnames $SLURM_JOB_NODELIST | \
awk '{print $1" slots=8"}' > /tmp/hostfile_$SLURM_JOB_ID

# 启动DeepSpeed训练
deepspeed \
--hostfile /tmp/hostfile_$SLURM_JOB_ID \
--master_addr $MASTER_ADDR \
--master_port $MASTER_PORT \
train_gpt.py \
--deepspeed_config ds_config.json

Slurm在AI大模型训练中的核心价值

作业检查点与断点续训

长时间训练任务(数天甚至数周)不可避免地面临硬件故障风险。Slurm提供了完善的检查点机制:

#!/bin/bash
#SBATCH --job-name=long-pretrain
#SBATCH --time=7-00:00:00
#SBATCH --signal=SIGUSR1@90 # 作业超时前90秒发送信号

# 在Python代码中捕获信号实现优雅退出和检查点保存
python train.py --resume_from_checkpoint /checkpoints/latest

同时,训练代码中可以捕获SIGUSR1信号,在收到信号时保存检查点,作业结束后再提交续训作业。

资源调度可视化监控

可通过sinfosacct结合自定义脚本实现集群状态监控:

# 查看所有GPU节点的实时使用情况
watch -n 5 'sinfo -N -p train -o "%12N %10G %10T %8C %8m" | grep -v drain'

# 统计过去24小时GPU使用率
sacct \
--starttime=$(date -d '24 hours ago' +%Y-%m-%dT%H:%M:%S) \
--format=User,JobID,AllocTRES%50,Elapsed \
--state=COMPLETED

公平调度与多团队协作

在多AI团队共享GPU集群的场景中,Slurm的公平树(Fair Tree)调度算法能够保证:

  • 长期低使用率的用户获得更高调度优先级
  • 短期突发使用不影响其他团队的长期公平份额
  • 管理员可为不同团队设置GPU配额

这是Kubernetes原生调度器目前较难实现的功能。

参考资料