在 AI for Science 平台落地异构调度:从「数据搬运工」到「算力调度器」的架构重构实录
在 AI for Science 平台落地异构调度从「数据搬运工」到「算力调度器」的架构重构实录上周有个需求砸下来院里新建的 AI for Science 协作平台要上线对外开放支撑分子动力学MD长周期模拟与大模型预训练混部。测试环境跑通的流程一到生产环境就炸——不是 OOM 就是存储 IO 打满研究员提个任务排队 6 小时起步跑俩小时挂了还得从头来过。项目背景简单交代上海某研究院自建算力集群约 200 张 H800 500 张 A800存储端挂着 3PB CephFSCeph 18.2.2 Quincy和 200TB Alluxio 缓存层。技术栈锁定在 Kubernetes 1.29.4、Slurm 23.11.8、KubeRay 1.1.0、Spring Boot 3.3.2JDK 21.0.3、Fluid 0.9.0Alluxio Runtime 2.9.3。核心痛点不在模型算法而在异构负载下的数据亲和性调度与有状态长任务的生存保障。背景混部场景下的「三高」噩梦先说业务画像。分子动力学典型作业单任务跑 7×24 小时甚至数周MPI 进程间通信极其敏感中断一次等于白跑Checkpoint 文件动辄 2TB大模型预训练则是 Gang Scheduling 启动PyTorch DDP NCCL对带宽抖动零容忍但支持 Tensor Parallel 切分、支持频繁torch.save。这俩负载混在同一套 K8s 集群里还要套一层多租户配额研究组级别Slurm 管着裸金属 MPI 任务K8s 管着容器化训练任务中间隔着一层自研的统一提交网关。测试阶段没暴露问题因为测试数据集小、并发低、无抢占。真实上线第一周三个指标扎眼跨节点数据拉取占任务总耗时 68%Alluxio 缓存命中率仅 12%万兆网卡跑满却喂不饱 GPU。Slurm 抢占 K8s 任务导致 PyTorchJob 重启率 43%无法恢复研究员直接在群里骂娘。配额失效A 组提交 50 张卡的 RayJobB 组 8 张卡的 MD 任务排队饿死Kueue 的 ClusterQueue 配置在 Gang Scheduling 面前形同虚设。过程把「数据搬到算力」改成「算力贴着数据转」1. 调度层拆解别让 K8s 调度器干不擅长的事最早想用 K8s 原生kube-schedulerSchedulerPlugin解决数据亲和性写了个PreFilter插件去查 FluidDatasetCR 的status.nodes字段再给 Pod 打nodeAffinity。压测发现调度延迟 P99 从 200ms 飙到 3.4s因为每个 Pod 创建都要 List 所有 Dataset CR、计算拓扑距离、打分排序调度器主线程被卡死。换路子了。引入Scheduler ExtenderHTTP 扩展器做「粗筛」只在Filter阶段调用逻辑下沉到独立 Go 服务scheduler-extender-v0.3.1缓存 Dataset 节点分布在本地 RedisValkey 7.2.5单次请求 15ms 以内。K8s 原生插件只保留Score阶段做微调。java// Spring Boot 网关侧任务提交时自动注入数据亲和性标签不依赖用户手填 YAMLRestControllerRequestMapping(/api/v1/jobs)RequiredArgsConstructorpublic class JobSubmitController {private final FluidDatasetClient fluidClient; // Feign 调用 Fluid Controllerprivate final SchedulerExtenderClient extenderClient;private final KubernetesClient k8sClient;PostMappingpublic ResponseEntity submit(Valid RequestBody JobSubmitRequest req) {// 1. 解析数据集引用查询 Fluid 缓存分布List datasetNames req.getDatasetRefs();Map datasetNodeMap fluidClient.getCachedNodes(datasetNames);if (datasetNodeMap.isEmpty()) {throw new BusinessException(DATASET_NOT_CACHED, 目标数据集未预热至任何节点请先提交预热任务);}// 2. 计算最优节点集合交集优先并集兜底Set candidateNodes computeOptimalNodes(datasetNodeMap, req.getGpuCount());// 3. 构建 PodSpec注入 nodeAffinity tolerations专用节点池污点Pod jobPod buildPodSpec(req, candidateNodes);// 4. 根据负载画像分发MPI - Slurm OperatorDDP/Ray - Kueue K8s JobSetif (req.getWorkloadType() WorkloadType.MPI_MD) {return submitToSlurm(jobPod, req);}return submitToKueue(jobPod, req);}private Set computeOptimalNodes(Map datasetNodeMap, int gpuCount) {// 简单启发式求交集不足则按缓存完整度评分取 Top-Nreturn datasetNodeMap.values().stream().reduce((a, b) - a.stream().filter(b::contains).collect(Collectors.toList())).orElseGet(() - datasetNodeMap.values().stream().flatMap(List::stream).collect(Collectors.groupingBy(Function.identity(), Collectors.counting())).entrySet().stream().sorted(Map.Entry.comparingByValue().reversed()).limit(gpuCount / 8 2) // 每节点 8 卡冗余 2 个节点.map(Map.Entry::getKey).collect(Collectors.toSet()));}} 这个方案虽然官方文档不推荐 Extender维护成本高但在我们「数据集固定、节点拓扑变化慢」的场景下比插件模式稳得多。插件模式适合通用调度器开发我们是业务侧深度定制别被「最佳实践」绑架。2. 抢占与生存CRIU 在 GPU 场景是个坑应用层 Checkpoint 才是正解Slurm 抢占 K8s 任务最初想用 CRIU (3.17.1) 做容器级热迁移/检查点。实测发现CRIU 根本 Dump 不下来显存状态cuda-checkpoint只能存 host 侧内存恢复时 NCCL Communicator 直接炸报ncclInternalError。折腾两周放弃。转而强制要求业务侧实现应用层 Checkpoint 接口平台侧只负责「发信号、存制品、拉起新实例」。yamlKueue JobSet 模板定义 PreStop Hook 共享 PVC 挂载 Checkpoint 目录apiVersion: jobset.x-k8s.io/v1alpha2kind: JobSetmetadata:name: ${{JOB_NAME}}spec:replicatedJobs:name: workerreplicas: ${{GPU_COUNT}}template:spec:serviceAccountName: jobset-sarestartPolicy: OnFailurevolumes:name: ckpt-volumepersistentVolumeClaim:claimName: ${{PVC_NAME}}containers:name: trainerimage: ${{IMAGE}}command: [bash, -c, torchrun --standalone --nnodes1 --nproc_per_node8 train.py --ckpt-dir /ckpt]volumeMounts:mountPath: /ckptname: ckpt-volumelifecycle:preStop:exec:command: [/bin/sh, -c, touch /ckpt/SIG_CHECKPOINT sleep 120] # 留 2 分钟刷盘env:name: PLATFORM_CHECKPOINT_SIGNALvalue: SIGUSR1 # 应用层监听信号触发 torch.save平台侧控制器job-lifecycle-controller v0.4.0监听PodDeletionTimestamp发现被抢占立即Patch PodterminationGracePeriodSeconds180防止默认 30s 截断。向容器发SIGUSR1业务代码捕获后执行torch.save({model: ..., optimizer: ..., rng: ...}, f/ckpt/ckpt_rank{dist.get_rank()}_step{step}.pt)。等待SIG_CHECKPOINT文件出现或超时再允许 Pod 彻底终止。重建 JobSet 时initContainer自动探测/ckpt最新 step传入--resume-step启动。效果MD 任务虽不支持热迁移但应用层每 30 分钟落盘一次PLUMEDRESTART关键字抢占恢复仅丢 ≤30 分钟算力研究员能接受。3. 多租户配额Kueue Slurm 统一视图的「伪全局调度」Kueue 管不了 SlurmSlurm 管不了 K8s。搞了个中间层quota-syncerGo 协程每 10s 跑一次从 Slurmsacctmgr show assoc formataccount,GrpTRESMins拿各账户已用 GPU 分钟数。从 KueueClusterQueue.status.flavors[].used拿 K8s 侧占用。汇总写入 Redisquota:{org_id}:used_gpu_minutes提交网关准入时只看这键。go// quota-syncer 核心同步逻辑片段func (s *Syncer) syncLoop() {ticker : time.NewTicker(10 * time.Second)for range ticker.C {slurmUsage, _ : s.slurmClient.GetAccountUsage() // map[org]float64 (gpu-min)kueueUsage, _ : s.kueueClient.GetClusterQueueUsage() // map[org]float64merged : make(map[string]float64)for k, v : range slurmUsage { merged[k] v }for k, v : range kueueUsage { merged[k] v }pipe : s.redis.Pipeline()for org, used : range merged {limit : s.getQuotaLimit(org) // 从 CM 读配额上限pipe.Set(ctx, fmt.Sprintf(quota:%s:used, org), used, 0)pipe.Set(ctx, fmt.Sprintf(quota:%s:limit, org), limit, 0)// 提交网关 Lua 脚本原子检查if used request limit then reject}_, _ pipe.Exec(ctx)}}提交网关侧 Lua 脚本保证原子性lua-- check_and_consume_quota.lualocal used_key KEYS[1]local limit_key KEYS[2]local request tonumber(ARGV[1])local used tonumber(redis.call(GET, used_key) or 0)local limit tonumber(redis.call(GET, limit_key) or 0)if used request limit thenreturn {0, used, limit} -- 拒绝endredis.call(INCRBY, used_key, request)return {1, used request, limit} -- 通过方案对比为何放弃「全 K8s」与「全 Slurm」| 维度 | 纯 K8s (Kueue JobSet MPI Operator) | 纯 Slurm (Pyxis Enroot) |混合模式当前落地|| :--- | :--- | :--- | :--- ||MPI 通信性能| 依赖 HostNetwork 手动亲和性NCCL 拓扑感知弱 | 原生srun --mpipmi2拓扑感知最优 |Slurm 独占 MPI 池零损耗||容器化生态兼容| 原生支持 Ray/PyTorchJob/KubeFlow | 需 Enroot 转镜像调试链路长 |K8s 侧原生Slurm 侧仅跑传统 MPI||抢占/回收粒度| Kueue Preemption 支持优先级但 Gang Scheduling 易死锁 | Slurm 抢占成熟但无感知容器状态 |分域抢占Slurm 抢 SlurmKueue 抢 K8s跨域仅配额联动||数据亲和性调度| Scheduler Plugin/Extender 灵活 |sbatch --constraint表达力弱 |Extender Fluid 缓存感知跨域数据预热走统一 DataLoad Job||运维复杂度| 单一栈但 MPI Operator 仍不稳定 (v0.7.0) | 成熟稳定但容器化体验差 |双栈运维成本 30%换取业务零改造上线| 别信「一套调度器走天下」。MPI 死磕 K8s 是给运维找罪受PyTorch 死磕 Slurm 是给研发找罪受。分域治理、配额联动、数据解耦才是混部的务实解。效果数字说话上线 3 周观测窗口2026-07-01 至 2026-07-21对比重构前基线| 指标 | 重构前 | 重构后 | 变化幅度 || :--- | :--- | :--- | :--- ||平均数据加载耗时首轮 Epoch/Step| 2h 14min |18min|↓ 86.5%||Alluxio 缓存命中率| 12% |91%|↑ 79pp||任务排队 P99 时长| 4h 12min |19min|↓ 92.4%||抢占导致的有效算力损失| 100%全量重跑 |≤ 30min/次|↓ 99%||集群 GPU 平均利用率| 45% |78%|↑ 33pp||跨租户配额争抢投诉| 日均 6 单 |0 单|清零|存储侧顺带优化了 Cephosd_op_threads8、bluestore_min_alloc_size64K针对 2MB 大块顺序读配合 Alluxioalluxio.user.file.readtype.defaultCACHE_PROMOTE单节点顺序读吞吐从 3.2 GB/s 稳在 9.8 GB/s接近 100Gbps 网卡物理上限。总结后端架构的「确定性」不在模型层在调度层这回重构的核心心得就三条数据亲和性调度必须下沉到 Extender/Operator 层别指望业务侧写nodeSelector也别指望通用调度器插件能扛住高并发打分。GPU 任务的 Checkpoint 是应用层契约不是基础设施魔法。CRIU 在显存面前失效强制约定SIGUSR1torch.save/ PLUMED RESTART平台只负责信号传递与制品版本管理。异构集群别强行合一Slurm 管 MPI、K8s 管 Cloud-Native Training配额层做最终一致性同步即可别试图搞统一调度器那是架构师的自嗨不是工程师的交付物。下一步打算把quota-syncer替换成基于 KueueAdmissionCheck的原生准入链路把 Slurm 用量作为外部指标喂给 Prometheus Adapter再砍掉一层 Redis 中间商。不过那是下个迭代的事了——当下集群跑稳了研究员不骂娘了这才是后端交付的硬指标。#后端 #Java #SpringBoot #Kubernetes #Slurm #AI4S #异构调度你在实际项目中有遇到类似问题吗欢迎在评论区分享你的经验和解决方案。

相关新闻

AutoHotkey v1到v2脚本迁移完整解决方案:架构演进与技术债务管理的终极指南

AutoHotkey v1到v2脚本迁移完整解决方案:架构演进与技术债务管理的终极指南

AutoHotkey v1到v2脚本迁移完整解决方案:架构演进与技术债务管理的终极指南 【免费下载链接】AHK-v2-script-converter AHK v1 -> v2 script converter 项目地址: https://gitcode.com/gh_mirrors/ah/AHK-v2-script-converter 随着AutoHotkey v2的推出&am…

2026/7/31 1:13:09阅读更多 →
AI竞对监测失效?92%团队漏掉这4类非结构化信号,附自动化抓取Python脚本

AI竞对监测失效?92%团队漏掉这4类非结构化信号,附自动化抓取Python脚本

更多请点击: https://kaifayun.com 第一章:AI竞对监测失效?92%团队漏掉这4类非结构化信号,附自动化抓取Python脚本 当AI产品团队紧盯竞品官网更新日志、App Store评分和财报数据时,真正影响市场格局的信号往往藏在非结…

2026/7/31 1:13:09阅读更多 →
AI工具红利正在消失,你的副业还能撑几个月?——基于127个案例的可持续性衰减曲线预警

AI工具红利正在消失,你的副业还能撑几个月?——基于127个案例的可持续性衰减曲线预警

更多请点击: https://intelliparadigm.com 第一章:AI工具红利正在消失,你的副业还能撑几个月?——基于127个案例的可持续性衰减曲线预警 过去18个月内,我们系统追踪了127个依托AI工具(如MidJourney、Claud…

2026/7/31 1:13:09阅读更多 →
游戏性能优化实战:解决GC频繁触发导致的帧率卡顿问题

游戏性能优化实战:解决GC频繁触发导致的帧率卡顿问题

1. 项目概述:当游戏帧率被GC“偷袭”做游戏开发,尤其是移动端或者对性能要求苛刻的平台,最怕的就是画面突然卡顿。玩家正沉浸在激烈的对战或者精美的场景中,突然画面一滞,帧率(FPS)从流畅的60直…

2026/7/31 4:53:46阅读更多 →
功能开发插件的智能代理架构

功能开发插件的智能代理架构

功能开发插件的智能代理架构 【免费下载链接】claude-code Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows -…

2026/7/31 4:53:46阅读更多 →
ACS712霍尔电流传感器PCB布局与软件校准实战指南

ACS712霍尔电流传感器PCB布局与软件校准实战指南

1. 从电流检测到PCB布局:ACS712的实战设计全解 最近在做一个需要精确监测电机电流的项目,选型时ACS712这个经典的霍尔效应电流传感器芯片又一次进入了我的视线。它结构简单、隔离性好,但真要把它用稳、用准,尤其是在PCB布线环节&a…

2026/7/31 4:53:46阅读更多 →
稳压二极管限流电阻选型详解:从公式到实战避坑指南

稳压二极管限流电阻选型详解:从公式到实战避坑指南

1. 从一次电路冒烟说起:为什么限流电阻不是“随便选”那天下午,我正在调试一块新设计的电源板。板上需要一个简单的5V基准电压,给一颗运放供电。电路再简单不过:输入是12V,用一个1N4733A(5.1V稳压管&#x…

2026/7/31 4:53:46阅读更多 →
关于linux里面的exec系列

关于linux里面的exec系列

其实有六种以exec开头的函数,统称exec函数: exec 系列函数&#xff1a;调用后直接替换当前进程的代码段&#xff01; 成功执行 → 原有 main 函数后续代码永远不会运行 只有调用失败&#xff0c;函数才会返回&#xff0c;继续往下执行。 #include <unistd.h> int execl(…

2026/7/31 4:53:46阅读更多 →
拔掉网线后TCP连接状态变化与检测机制深度解析

拔掉网线后TCP连接状态变化与检测机制深度解析

1. 先搞清楚面试官到底想问什么这个问题看似简单&#xff0c;但90%的候选人会栽在细节理解上。面试官问“拔掉网线后TCP连接是否存在”&#xff0c;其实是在考察三个层面的理解&#xff1a;第一层&#xff1a;TCP协议层面的连接状态如何变化。第二层&#xff1a;操作系统内核中…

2026/7/31 4:51:46阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

&#x1f539; 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具&#xff0c;凭借本地离线运行、可视化图形操作和任务自动化三大核心特性&#xff0c;赢得了众多用户的青睐。与普通在线对话AI工具不同&#xff0c;它属于能够直接操控本机软硬件的智能数字员工…

2026/7/30 15:03:16阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接&#xff0c;是用激光束对阀座壳体&#xff08;通常为不锈钢或铝合金&#xff09;进行密封焊接&#xff0c;使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/30 12:22:27阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX&#xff1a;三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/30 15:13:02阅读更多 →
物理复制比逻辑复制好在哪?数据库复制原理详解

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制&#xff0c;分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件&#xff0c;物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB&#xff08;云原生数据库&#xff09;采用物理复制&#xff0c;在同步延迟、数据…

2026/7/31 0:00:40阅读更多 →
BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown&#xff1a;3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader &#x1f633; 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:00:41阅读更多 →
有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前&#xff0c;游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据&#xff0c;中国AI游戏云市场规模已达18.6亿元&#xff1b;同时&#xff0c;游戏研发环节AI渗透率高达86%&#xff0c;生成式AI内容普及率超过50%。面对庞大的市场&#xff0c;游戏…

2026/7/31 0:00:41阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时&#xff0c;发现推理速度只有可怜的 1-2 FPS&#xff0c;而别人的演示视频却能跑到 30 FPS 以上&#xff0c;那么问题很可能不在模型本身&#xff0c;而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后&#xff0c;会直接使用官方示例…

2026/7/31 0:49:33阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一&#xff1a;为什么你需要了解 Coze 和 Dify&#xff1f;如果你对 AI 应用开发感兴趣&#xff0c;但一看到“大模型”、“智能体”、“工作流”这些词就头疼&#xff0c;觉得门槛太高&#xff0c;那这篇文章就是为你准备的。很多开发者&#xff0c;包括我自己&#…

2026/7/30 4:47:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会&#xff1a;配图一直是个让人头疼的问题。2026年&#xff0c;AI生图工具已经非常成熟了&#xff0c;但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1&#xff1a;速度之王2026年6月11日&#xff0c…

2026/7/30 15:43:46阅读更多 →