智算中心算力规划与部署落地指南:测算、液冷、驱动与调度池化
简介:《智算技术与算力规划设计及部署实施方案v2.0.pdf》面向智算中心规划建设、算力平台架构设计及项目落地实施人员,适合需要梳理智算技术路线、编制算力规划方案或推进部署工作的技术人员与管理者参考。内容围绕智算技术与算力规划设计、部署实施展开,可用于理解智算中心建设中的方案组织思路、规划要点与实施关注项,帮助读者在方案编制、技术选型和项目推进时建立较完整的参考框架。资源共1个PDF文件,大小约11.28MB,单文件便于集中查阅、归档与二次整理,适合作为方案模板、技术材料或项目参考资料使用。目前已有131人学习,具备一定关注度。读者可从中获取智算技术方案的组织方式、算力规划设计的表达结构以及部署实施阶段的关键考虑点,用于内部汇报、方案初稿撰写或项目实施前的资料比对。
1. 从一张机柜清单开始:智算中心落地前先对齐的三件事
接手智算中心项目的人,十有八九是从一张机柜清单开始犯难的:加速卡型号定了、柜位排了,等系统装完才发现单柜功率顶到 30kW 以上,风冷压不住,卡一上负载就降频;或者驱动版本和训练框架对不上,任务跑十分钟掉一次卡,日志里除了一行设备超时什么都看不到。这份《智算技术与算力规划设计及部署实施方案 v2.0》要解决的正是中间这一段:把算力测算、供电制冷、系统安装、驱动与容器、调度池化、验收压测串成一条能照着走的线,而不是给一堆“高可用、高带宽”的空话。它适合正在做机房扩容、算力平台立项、或者接手别人半成品集群的工程师,尤其适合那种“设备已经到货、机柜已经通电,但没人说清楚下一步该敲哪条命令”的现场。版本上有个血泪经验:规划方案类文档一定要看修订版,v1 里的功率密度算法按 8kW 单柜写的,v2 才补上液冷边界,照老版本排柜,后面改造成本够再买半柜卡。
2. 算力测算与选型:把「要多少卡」算成一张能签字的表
方案文档翻开第一页往往就是一张算力表,但那张表是给立项会看的,不是给装机的人看的。真正要落到手上的,是三个数:需要多少张卡、单柜能不能扛住、验收时用什么指标判定“这套算力交付合格”。这三件事任何一件算错,后面章节的安装步骤都会变成返工。
我一般的顺序是:先用业务负载倒推有效算力,再用显存反推卡型档位,最后用功率把机柜定下来。顺序反了很容易出现“卡买大了但柜装不下”的翻车现场。
2.1 从业务负载倒推有效算力
厂商标称的峰值算力是稠密矩阵乘的理想值,真实训练跑不满。行业里通用的做法是先按 MFU(模型算力利用率)打折:预训练类 30%~45%,微调类 35%~50%,在线推理受 batch 和序列长度影响大,20%~60% 都可能。拿标称值直接除以目标算力,算出来的卡数通常少 30% 以上,最后只能靠加班解释。
| 负载类型 | 精度 | 单卡显存下限 | 卡间互联要求 | 选型档位 |
|---|---|---|---|---|
| 预训练 / 继续预训练 | BF16 | 64GB 起 | 高,需 400GB/s 级互联 | 训练档 |
| SFT、LoRA 微调 | BF16 | 40~80GB | 中 | 训练档 / 通用档 |
| 在线推理 | FP16 / INT8 | 24~48GB | 低 | 推理档 |
| 渲染、科学计算 | FP32 / FP64 | 按模型定 | 中 | 通用档 |
表里的“档位”不是型号,而是采购口径:训练档看互联和显存,推理档看性价比和单卡功耗,通用档看双精度能力。定档位之前先定业务形态,比先看报价单靠谱得多。下面这段粗算脚本可以直接改参数跑,用来在选型会上给出一个能自圆其说的数:
# 粗算集群规模:输入目标吞吐与单卡参数,输出卡数、整机数和显存下限 import math peak_tflops = 990 # 单卡 BF16 稠密峰值,按实际选型替换,单位 TFLOPS mfu = 0.38 # 训练场景 MFU,取 0.30~0.45,别用厂商标称值 target_pflops = 120 # 业务侧要求的有效算力,单位 PFLOPS redundancy = 0.20 # 冗余系数:故障替换 + 波峰,一般 15%~25% effective_per_card = peak_tflops * mfu / 1000 # 单卡有效算力(PFLOPS) cards = math.ceil(target_pflops / effective_per_card * (1 + redundancy)) nodes = math.ceil(cards / 8) # 按 8 卡整机折算 print(f"单卡有效 {effective_per_card:.3f} PFLOPS,需 {cards} 卡 / {nodes} 台整机") # 显存反推:全参训练每参数约 16~20 字节(权重+梯度+优化器状态+激活余量) params_b = 70 # 模型参数量,单位 B bytes_per_param = 18 total_mem_gb = params_b * 1e9 * bytes_per_param / 1024**3 print(f"模型总显存需求 {total_mem_gb:.0f} GB,除以并行卡数才是单卡占用")脚本里mfu这一行最值得吵:业务方希望取 0.5,装机的人知道实测只有 0.35。稳妥做法是按 0.35 报卡数、按 0.45 报性能承诺,中间那段差值就是上线后的调优空间。bytes_per_param取 18 是混合精度加 Adam 的常见口径,纯推理场景降到 2~4 即可,用同一个脚本算推理卡数会严重高估。
2.2 机柜功率与制冷:先算电,再定柜
算力规划里最容易被跳过的一节是供电。方案文档里有一句很关键的话:单柜功率密度决定制冷路线,而不是反过来。风冷机柜做到 12kW 已经很吃力,再往上要么背板空调,要么直接上冷板液冷。排柜的时候如果按“先塞满、以后再说”的思路做,后期改管路、换机柜、停机的代价比设备本身还贵。
| 单柜 IT 负载 | 典型形态 | 制冷方式 | 可接受 PUE |
|---|---|---|---|
| ≤ 8kW | 4 台 8 卡整机 | 风冷 + 冷热通道封闭 | 1.30~1.45 |
| 8~12kW | 6~8 台整机 | 风冷 + 背板空调 | 1.25~1.40 |
| 12~25kW | 8~16 台整机 | 冷板液冷 + CDU | 1.15~1.25 |
| > 25kW | 超密整机柜 | 液冷为主 | ≤ 1.15 |
供电侧按 IT 负载的 1.2~1.3 倍配 UPS,满载后备时间不低于 10 分钟;每个机柜走双 PDU 的 A/B 两路,单路各承担 50% 负载,任何一路掉电都不能让整柜断电。这些数字在方案里是参数,在现场就是能不能验收的硬指标。装机前我习惯先采一遍实际功耗,把“标称功率”换成“实测峰值”:
#!/usr/bin/env bash # 逐台读取带外管理口的瞬时功率与进风温度,用于复核机柜热密度 # hosts.txt 每行一个带外地址;账号密码走环境变量,不写进脚本 : "${BMC_USER:?请先 export BMC_USER}" : "${BMC_PASS:?请先 export BMC_PASS}" printf 'host,watts,inlet_c\n' > power.csv while read -r h; do w=$(ipmitool -I lanplus -H "$h" -U "$BMC_USER" -P "$BMC_PASS" \ dcmi power reading 2>/dev/null | awk '/Instantaneous/{print $4}') t=$(ipmitool -I lanplus -H "$h" -U "$BMC_USER" -P "$BMC_PASS" \ sdr type temperature 2>/dev/null | awk -F'|' '/Inlet/{gsub(/ /,"",$5); print $5}') echo "$h,${w:-NA},${t:-NA}" >> power.csv done < hosts.txtdcmi power reading取的是瞬时值,awk抓Instantaneous那一行的第 4 个字段;温度按Inlet关键字过滤进风口传感器,不同厂商的传感器命名不一样,先手工跑一台确认字段再批量。采样要坚持 30 分钟以上并取峰值,训练任务有同步波峰,只看均值会低估 15% 左右——这个低估在夏天就是过热降频。-I lanplus是带外管理的标准接口,走的是管理网,不要和业务网混在一起跑脚本。
2.3 把方案里的数字变成可验收的清单
“高带宽、高可用”这种描述没法验收,得换成能跑出来的数。方案文档里我认可的做法是给每个指标配一条验收方法,装完就照着测一遍,测不过不算交付。
| 指标 | 目标值 | 验收方法 |
|---|---|---|
| 单卡有效算力(MFU) | 训练 ≥ 35% | 跑标准 benchmark,看 step time |
| 卡间互联带宽 | ≥ 标称值 85% | 厂商带宽测试 / all-reduce 实测 |
| 节点间网络时延 | ≤ 10μs(无损以太) | 时延测试工具 + 交换机计数 |
| 并行存储读带宽 | ≥ 每节点 5GB/s | fio 多机并发读 |
| 集群可用率 | 月度 ≥ 99% | 监控平台统计 |
| 单作业排队时长 | P90 ≤ 15min | 调度器日志统计 |
装机当天还有一件事必须做:把每台机器的硬件基线采下来留档,后面出现“这台机器比别的慢”的时候,有对比才有结论。
#!/usr/bin/env bash # 采集节点硬件基线,装机后立刻跑一遍并留档 { echo "== host =="; hostname; date -Is echo "== cpu =="; lscpu | grep -E 'Model name|Socket|Core|NUMA' echo "== mem =="; free -g | awk 'NR==2{print $2" GB total"}' echo "== disk =="; lsblk -d -o NAME,SIZE,ROTA,MODEL | grep -v loop echo "== accel =="; lspci -nn | grep -Ei '3d controller|processing accel' echo "== nic =="; lspci -nn | grep -Ei 'ethernet|infiniband' } | tee "/var/log/inventory-$(hostname).log"lscpu只抓四类字段,避免日志太长;lsblk -d只看整盘不看分区,ROTA为 0 表示固态;lspci用3d controller和processing accel两个设备类过滤加速卡,用ethernet/infiniband过滤网卡。这份日志后面排查“为什么这台机器少认了两张卡”时会救你一命,比翻装机单快得多。
3. 系统与驱动安装:固件、内核、运行时按顺序压进去
这一章是整个部署里最容易返工的部分。装坏一台机器不可怕,可怕的是 32 台机器装出 5 种状态,后面调度器报错你都分不清是软件问题还是硬件问题。我的做法是:先把 BIOS 和固件统一,再把内核参数固化进配置文件,最后按“依赖 → 驱动 → 容器引擎 → 运行时 hook”的顺序一次性装完,中间不重启多余次数。
3.1 上架先改 BIOS:这六项不改,后面基本会出问题
| 选项 | 取值 | 不改的后果 |
|---|---|---|
| Above 4G Decoding | Enabled | 大显存卡地址空间不够,系统只认到部分卡 |
| Resizable BAR | Enabled | 同上,驱动初始化变慢甚至失败 |
| IOMMU | Enabled | 容器直通、设备隔离全部失效 |
| 电源/性能策略 | Maximum Performance | 卡降频,实测掉 10%~15% 算力 |
| 风扇策略 | 全速或线性 | 高密机柜进风 35℃ 以上直接过热降频 |
| 启动模式 | UEFI,关闭 Legacy | 大于 2TB 的系统盘装不上 |
另外一条不成文规矩:同一批次的机器,BIOS 和固件版本必须一致,最好在上架前统一刷一遍。混版本最典型的症状是“同样型号的卡,一半机器能识别满,一半少一张”,查半天以为是卡坏了,其实是固件差异。
3.2 操作系统与内核参数:写进配置文件,别手敲
操作系统我一般选 Ubuntu 22.04 LTS,内核 5.15;新卡平台建议直接上 6.x HWE 内核,老内核认不全新设备。装完第一件事是关掉自动升级,第二件事是把内核参数固化下来。
# 1) 内核启动参数:IOMMU 直通、1G 大页、THP 改为 madvise sudo sed -i 's/^GRUB_CMDLINE_LINUX=.*/GRUB_CMDLINE_LINUX="intel_iommu=on iommu=pt default_hugepagesz=1G hugepagesz=1G hugepages=64 transparent_hugepage=madvise"/' /etc/default/grub sudo update-grub && sudo reboot # 2) 内存与网络参数,落到 sysctl.d 而不是每次手敲 sudo tee /etc/sysctl.d/99-ai-cluster.conf >/dev/null <<'EOF' vm.swappiness = 10 vm.zone_reclaim_mode = 0 kernel.numa_balancing = 1 fs.file-max = 2097152 net.core.rmem_max = 134217728 net.core.wmem_max = 134217728 EOF sudo sysctl --system # 3) 校验是否生效,没生效说明 grub 没更新或者被别的配置覆盖 grep -o 'iommu=[a-z]*' /proc/cmdline grep HugePages_Total /proc/meminfointel_iommu=on在 AMD 平台上换成amd_iommu=on;iommu=pt只给直通设备建映射表,比全量映射性能好,是通用做法。hugepages=64预留 64GB 大页给推理服务和部分数据库,训练本身用不到这么多,按业务调。vm.swappiness=10是防止内存压力下把训练进程换出到磁盘,一旦换出,step time 会从秒级变成分钟级。numa_balancing=1打开内核自动迁移,但训练进程仍然建议用绑核工具手动绑,自动迁移在跨 NUMA 场景下反而是噪声源。
注意:大页要按 NUMA 节点分配,单节点机器写
hugepages=64没问题,双路机器最好写hugepages=32,32,否则一个节点分完、另一个节点分不到,启动大页服务时直接失败。
3.3 驱动与运行时:先对齐版本,再谈安装
驱动版本这件事,我给的建议永远是“三层对齐”:驱动分支、容器运行时 hook、深度学习框架,三者错一代就出问题。最常见的翻车是框架镜像里带的运行时比宿主驱动新,容器一起来就报运行时初始化失败。
| 层级 | 取值示例 | 说明 |
|---|---|---|
| 操作系统内核 | 5.15 / 6.5 HWE | 新卡平台要 6.x |
| 加速卡驱动 | 分支 A(如 550 系) | 与内核、固件匹配 |
| 运行时 hook | 与驱动同代 | 低一代表现为容器内看不到卡 |
| 深度学习框架 | 与运行时对应 | 框架包自带运行时,别混装 |
| 容器基础镜像 | 镜像内运行时 ≤ 宿主 | 向上兼容,向下不保证 |
安装顺序固定为:编译依赖 → 屏蔽开源显卡驱动 → 驱动 → 容器引擎 → 运行时 hook。中间任何一步跳过,后面都要重来。
# 1) 编译依赖:驱动要现场编译内核模块,缺 dkms 后面必踩 sudo apt-get update sudo apt-get install -y build-essential dkms linux-headers-$(uname -r) pkg-config # 2) 屏蔽发行版自带的开源显卡驱动,否则装完重启黑屏或掉卡 printf 'blacklist nouveau\noptions nouveau modeset=0\n' | sudo tee /etc/modprobe.d/blacklist-nouveau.conf sudo update-initramfs -u # 3) 静默安装厂商驱动包,--dkms 挂进内核升级链,这是后悔药 sudo sh ./gpu-driver-*.run --silent --dkms --no-opengl-files # 4) 重启后校验:列卡、看拓扑、跑带宽 sudo reboot nvidia-smi -q | head -20 # 卡型确定后按厂商设备管理命令替换 nvidia-smi topo -m # 输出 SYS/PHB/PIX/NVL,绑核要用--dkms是整段里最重要的参数,它让驱动在内核升级后自动重编;不加的话,一次apt upgrade就能让整柜机器掉卡,而且报错信息极其含糊,属于典型的“黑匣子”故障。--no-opengl-files避免覆盖系统 GL 库,带图形界面的机器不加这个参数,重启后进不了桌面。topo -m的输出里,SYS表示两张卡跨 NUMA,NVL/PIX表示同一条高速链路,后面写绑核脚本就靠这张表。
3.4 容器引擎与设备直通:让容器看得见卡
容器引擎的配置不多,但每一条都有理由。数据目录一定要挪到数据盘,镜像层和容器日志增长很快,系统盘 200GB 撑不过一个季度。
# 容器数据目录单独挂大盘,日志做滚动,别让日志写满盘 sudo mkdir -p /data/docker sudo tee /etc/docker/daemon.json >/dev/null <<'EOF' { "data-root": "/data/docker", "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m", "max-file": "3" }, "default-ulimits": { "memlock": { "Name": "memlock", "Hard": -1, "Soft": -1 } } } EOF sudo systemctl restart docker # 装运行时 hook,把设备节点和驱动库注入容器 sudo apt-get install -y container-toolkit sudo container-toolkit configure --runtime=docker sudo systemctl restart docker # 验证:容器内必须看到全部加速卡 docker run --rm --gpus all registry.local/base/gpu-check:latest gpu-smi -Lnative.cgroupdriver=systemd必须和后面 kubelet 的 cgroup 驱动一致,不一致时 kubelet 起不来,报错是misconfigured cgroup driver,看着像集群问题其实是容器引擎配置问题。memlock设成无限是 RDMA 和大页的老要求,不设的话多机通信初始化阶段就失败。max-size/max-file限住日志,训练容器一天能写几十 GB 日志,不滚动必然撑爆盘。
3.5 多机互信、时间同步与防火墙
单机装完只是开始,多机之间还有三件小事:关交换、对时间、铺互信。任何一件没做,分布式训练都会在奇怪的地方失败。
# 1) 关交换分区:k8s 和分布式训练都要求,重启后也不能回来 sudo swapoff -a && sudo sed -ri '/\sswap\s/s/^#?/#/' /etc/fstab # 2) 时间同步:偏差超过 1s,集合通信会直接超时 sudo apt-get install -y chrony sudo tee /etc/chrony/chrony.conf >/dev/null <<'EOF' server ntp1.internal iburst server ntp2.internal iburst makestep 1.0 3 EOF sudo systemctl restart chrony && chronyc sources -v # 3) 节点互信:装机阶段一次性铺好 ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519 for h in $(cat /etc/hosts.cluster); do ssh-copy-id -o StrictHostKeyChecking=no "$h"; donesed那一行是把 fstab 里的 swap 行注释掉,只swapoff不注释,重启后交换分区会自己回来。makestep 1.0 3表示前三次同步如果偏差超过 1 秒就强制跳变,而不是慢慢调,装机阶段需要的是快速对齐而不是平滑。chronyc sources -v里每行前面的^*才是当前同步源,看到^?说明没连上,多半是内网 NTP 地址写错或防火墙挡了 UDP 123。
4. 调度与资源池化:Kubernetes 与 Slurm 怎么选、怎么配
机器装完只是硬件池,真正的算力平台还要一层调度。这一步选错方向的代价很大:训练团队要的是长时间独占和拓扑感知,推理团队要的是弹性伸缩和服务发现,两拨人的诉求从来不一致。方案文档里给的建议是“按作业形态选,不按技术栈选”,这点我认同。
4.1 二选一判断表
| 维度 | Kubernetes | Slurm |
|---|---|---|
| 主要作业形态 | 在线服务、短任务、弹性推理 | 长时训练、批量计算、MPI 作业 |
| 多租户隔离 | 命名空间 + 配额,粒度细 | 分区 + QOS,粒度粗但直接 |
| 弹性伸缩 | 强,适合波峰波谷 | 弱,节点基本静态 |
| 拓扑感知 | 需要额外组件 | 原生支持 |
| 运维成本 | 高,组件多 | 低,配置文件为主 |
| 生态 | 服务治理、网关、监控齐全 | 高性能计算工具链成熟 |
我的常见做法是两者共存:推理服务和内部工具跑在 Kubernetes 上,长时训练和大规模并行作业交给 Slurm,两边共享同一套并行存储和同一张高速网络。如果团队只有一个调度运维,别硬上双栈,先按主力形态选一个,把另一个留到二期。
4.2 Slurm 侧:控制节点、队列与设备资源
Slurm 的配置集中在slurm.conf和gres.conf两个文件,改完必须所有节点同步,节点上的版本要和控制节点一致,否则会出现“作业提交成功但一直排队”的诡异状态。
# /etc/slurm/slurm.conf 关键行,其余保持默认 ClusterName=ai-prod SlurmctldHost=ctrl01 SelectType=select/cons_tres # 按可消费资源分配,必须开,否则 GPU 不参与调度 SelectTypeParameters=CR_Core_Memory GresTypes=gpu # 打开设备通用资源 ProctrackType=proctrack/cgroup # 用 cgroup 追踪进程,防作业退出后残留 TaskPlugin=task/cgroup ReturnToService=2 # 节点恢复后自动回到空闲,省掉手工恢复 SchedulerType=sched/backfill # 回填调度,小作业不被大作业堵死 PriorityType=priority/multifactor# /etc/slurm/gres.conf,按索引声明每台机器上的设备节点 NodeName=gpu[001-032] Name=gpu Type=train File=/dev/nvidia[0-7]SelectType=select/cons_tres是最容易漏的一行,漏了之后 GPU 不参与资源计算,一台 8 卡机器会被塞进 8 个各要一张卡的作业,看起来“调度很满”,实际互相抢显存。ProctrackType=proctrack/cgroup保证作业被杀时子进程一起清掉,不带 cgroup 的追踪方式经常留下僵尸进程占着显存。backfill回填调度能让短作业插空跑,队列观感会好很多。gres.conf里的File=/dev/nvidia[0-7]是按常见设备节点命名写的,其他卡型按厂商驱动实际生成的节点名替换,写完用scontrol show node确认Gres字段是gpu:8而不是gpu:0。
4.3 Kubernetes 侧:设备插件与资源声明
Kubernetes 管加速卡靠设备插件,插件以 DaemonSet 形式跑在每个卡节点上,负责把设备数量注册成扩展资源。这一步最容易出错的地方不是部署,而是资源名和调度约束写错。
# device-plugin-daemonset.yaml 片段,镜像按卡型厂商提供替换 apiVersion: apps/v1 kind: DaemonSet metadata: name: gpu-device-plugin namespace: kube-system spec: selector: matchLabels: { app: gpu-device-plugin } template: metadata: labels: { app: gpu-device-plugin } spec: nodeSelector: accelerator: "train" # 只调度到打了标签的卡节点 tolerations: - key: accelerator operator: Exists effect: NoSchedule containers: - name: plugin image: registry.local/k8s/gpu-device-plugin:1.0 securityContext: { privileged: true } volumeMounts: - { name: dev, mountPath: /dev } - { name: sys, mountPath: /sys } volumes: - { name: dev, hostPath: { path: /dev } } - { name: sys <p> <a href="https://download.csdn.net/download/u010412890/90479468" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>