作者 | 曾奥涵
智谱成立于 2019 年,源于清华大学计算机系知识工程实验室 (KEG) 的技术成果。2022 年,智谱训练并开源了中英双语预训练模型 GLM-130B,其性能媲美 GPT-3。2023 年发布了千亿参数极速对话模型 ChatGLM 系列,在 Hugging Face 社区获得了超过一千万次下载。2024 年,发布的旗舰模型 GLM-4-Plus 在 SuperBench 大模型评测中位列世界前三。
智谱的基础设施团队经历了从支持不足 10 人发展到要支持 200 多人研发团队的过程。本文将介绍智谱基础设施发展的初期、扩张和成熟三个阶段的挑战与实践经验。希望通过这些分享,激发新的思路和观点。
1
引言
我们从 2021 年底开始参与模型的训练,负责 GLM-130B 高精度千亿模型的训练工作。团队的发展与模型的演进密切相关。在初期阶段,集群数量较少,研发团队人数不到 10 人,主要目标是支持基座模型的研发。随着大模型的崛起,团队进入了扩张阶段,集群数量增加,我们采用了灵活的资源调配策略。如今,团队已进入成熟阶段,集群数量增至 10 个以上,服务的用户人数超 200 人。此时,团队的关注点转向如何提升资源使用效率,减少多套集群带来的数据流转和调度成本。

目前,我们 GLM 基础设施团队的主要职责可以分为三大块:
基础设施建设:这一部分主要包括集群搭建、GPU 上架、计算网络的组网以及存储规划等底层设施的建设工作。
基础设施运维:我们负责保障设施的稳定运行,优化集群的稳定性,主动发现并处理故障节点。此外,还涉及一些繁琐的任务,如数据迁移、数据拷贝以及数据流转的管理工作。
支持研发团队的平台建设:我们为公司研发团队提供了“GLM 机器学习平台”。该平台支持公司整体研发需求,整合了 GPU、存储、镜像等资源,帮助研发团队进行算法开发与迭代。
目前,我们的资源高度分散,采用云上云下混合模式,集群数量超过 10 个,分布在不同地域,且 GPU 型号和网络类型各异,导致异构性问题突出。同时,存储系统也存在混合性,进一步加剧了资源管理的复杂性。最后,由于资源更迭速度较快,数据迁移和集群清理成为瓶颈,而数据初始化速度对训练至关重要。
接下来,我将详细介绍我们如何从最初的一两个集群发展到如今这种复杂的资源环境,以及我们采取了哪些措施来应对这些复杂的资源。
2
初期:从裸金属集群训练到平台建设探索
裸金属集群训练模型
最早在 2022 年左右,我们开始训练 GLM-130B 的模型,当时尚未有成熟的调度平台支持。团队初期的目标非常明确,即支持基座模型的预训练。 我们通过租赁一批机器,并以裸金属的形式进行交付,整个过程依赖手动管理。团队成员和任务是直接与机器绑定的,预训练任务与实验任务、微调任务分别分配给不同的机器,任务之间通过共享存储进行协调,环境管理完全由用户通过 MiniConda、Docker 等工具自行完成。这种模式存在诸多问题。
首先,环境配置极为困难。由于机器资源分散,团队将多个小组分配到不同的机器上,导致驱动、库和软件包等版本不一致。这种不一致会造成许多训练任务无法正常运行,环境配置成为了一个巨大的难题。
其次,人力成本较高。 由于没有统一的平台工具,所有的任务必须手动提交和管理,尤其是在裸机环境中。团队需要定期值班,监控任务是否正常运行,或通过脚本手动检查任务状态。如果任务失败,排查问题非常繁琐。虽然可以通过手动操作将故障的 GPU 节点移除,但有时节点问题较复杂,缺乏有效的工具时,排查过程可能需要几个小时,造成很大的心智负担。

最后,资源管理也非常困难。 在没有统一任务管理系统的情况下,团队成员只能按照固定的机器进行工作,且很难协调机器的使用情况。由于机器经常出现故障,我们无法清楚知道哪些机器正在运行,哪些机器有问题,整体资源管理效率低下。
适合大模型训练的简易调度平台
尽管裸金属集群这种模式能够加快推动基座模型训练工作的开展 ,但由于管理和操作上的种种问题,我们意识到这种裸金属的方式并不理想,我们开始探索开发平台化的管理工具,以应对这些挑战。
整理需求后,我们发现调度平台至少要满足以下 3 个需求:
训练任务化。能够将训练抽象成一个任务,通过 MPI/PyTorchDDP 框架进行拉起。能够感知任务的不同生命周期,完成状态判断和转移。能够支持多任务的灵活调度。
任务稳定性。能够查询任务日志,监控任务状态,在任务生命周期变更时通知用户。
无人值守训练。能够完成任务失败自动重试,自动推进训练任务进行。能够自动识别故障节点,自动封禁。能够筛查慢速节点,提高效率。

(简易调度平台)
由于我们的团队起源于实验室背景,最初我们尝试了一些类似于 Slurm 调度工具的方案,但发现这些工具更多地适用于超算环境,并不完全符合大模型时代多级训练的需求。因此,我们决定自行开发一套简易的调度平台。
于是,我们转向了 Kubernetes,通过 K8s 屏蔽底层异构资源差异,提供统一接口, 通过设备插件注入训练所需的 GPU、RDMA 等设备。同时,将训练环境镜像化,训练数据和结果存放在 PVC 中。
在此基础上,我们的调度平台实现了两个 CR(Custom Resource)。
第一个是训练任务,它定义了任务所需的镜像、挂载的数据卷以及节点数,并负责维护整个任务的生命周期。
第二个是任务队列,收集节点信息,将训练任务成组调度到合适到节点。
通过简易调度平台,我们实现了训练任务化。但是,由于 GPU 设备本身的高故障率,我们仍然需要一个自动化方案来实现无人值守训练。
任务稳定性:Node Agent - 主动故障发现与处理
在任务的稳定性方面,我们希望能够查询任务的日志状态,并在任务生命周期内进行状态变更。例如,当任务失败时,我们希望能够及时通知用户。此外,我们还期望实现无人值守的训练,即在任务失败时,系统能够自动重试并继续推进任务的运行,同时进行故障检测。
为此,我们采用了 Node Agent 的方式来主动进行故障检测与发现。通过节点故障探查和运维自动化、故障告警等手段,我们实现了故障的快速响应。
以 GPU 掉卡为例,故障处理流程大致如下:当 GPU 故障时, Node Agent 会首先感知到掉卡问题,并立即禁止该故障节点的调度同时将故障信息通知运维。由于 GPU 掉卡后任务无法继续运行,任务将直接失败。任务失败后,系统会自动触发重试机制,确保任务能够继续执行。
我们通过 Node Agent 主动封禁了故障节点,当任务失败后,系统会触发重试机制。重试时,任务会被调度到健康的节点上,确保任务能够正常运行。一旦任务调度成功,我们还通过飞书电话等通知工具及时告知模型训练人员,以便他们关注任务的健康状况。这一流程有效支持了我们最初基座模型的训练需求。
3
扩张期:构建机器学习平台
随着团队的扩张,我们的规模增长到接近 50 人,同时资源也扩展到 3 到 5 个集群。训练任务的种类也大幅增加,原先只做文本模型,现在已经涉及到图像生成、视频生成等多个领域,训练任务变得更加多样化。
在这个过程中,运维成本也显著上升。随着集群数量的增加,机器和 GPU 型号的多样化导致机器故障频发,任务失败的情况也变得更加频繁。管理的复杂度也随之增加。最初只有一个团队进行训练时,资源分配和内部协商相对简单。但随着规模的扩大,如何合理分配和管理资源,以及建立有效的统计机制,成为了新的挑战。
另外,安全隐患问题也逐渐显现。最早的模式是通过共享存储来处理集群内的数据,这虽然方便,但也存在较大安全隐患。例如,某些用户可能会不小心执行一些操作,导致存储空间被占满,从而影响其他任务的正常运行。
于是,我们基于 Kubernetes 构建了一个机器学习平台,底层实现了计算、存储和网络的统一管理,全部通过 K8s 进行协调。调度层通过 Operator 实现,我们使用了 Kubernetes 的原生资源对象来完成资源调度,避免了复杂的开发工作,基本上遵循了 K8s 的标准做法。
在训练平台层,我们还需要满足日常的开发需求,因此抽象出了开发机、训练任务和推理任务等工作负载。同时,设计了任务队列、存储池和个人卷等机制,用于资源分配和权限管理。此外,我们引入了多种保障机制,确保任务的顺利推进,并与运维团队紧密配合,确保重点任务的实施。

我们的目标是以下述四个特征来构建我们的机器学习平台:
易用性:我们需要提供一个统一的功能抽象,屏蔽不同业务资源的差异,确保用户能方便地访问和使用。此外,平台还需要提供多种访问方式,包括 Web 界面、 Web Shell、SSH 直连以及命令行工具(CLI),以适应不同用户的需求。我们还需要一个灵活的资源分配机制,确保资源能根据任务需求进行合理调配。
稳定性:我们希望平台能够实现无人值守的任务管理。在任务失败时,系统应能够自动重试,例如,基于已保存的 checkpoint 自动恢复训练。整个任务生命周期中,任务状态的变更应能及时通知相关人员,并且系统应能保留运行环境的 debug 日志,方便调试和故障排查。
高效性:在任务量大、节点多的情况下,我们需要优化存储管理,并确保镜像能够迅速分发到各个节点,以提高训练效率。这包括存储的优化和高效的资源调度,确保大规模任务的顺利执行。
安全性:我们希望可以进行细粒度的存储访问控制,以防止未经授权的访问。例如,防止敏感数据(如 SIP 数据)被未经授权的用户或不当操作者下载或盗取等。
平台功能 1:开发机抽象,共享 GPU 模式
接下来,我们介绍了平台中几个重要的抽象功能,并阐述了背后的设计考虑。
在传统的开发机模式中,通常会采用独占 GPU 和块存储的方式,即为每个开发机分配一个独立的 GPU 和一个持久化的存储(如云卷)。这种方式类似于 ECS 模式,用于长期的开发任务。我们没有选择这种模式,而是采用了共享 GPU 的模式,避免了 GPU 独占。存储方面,我们没有使用持久化的块设备存储,而是依赖于 Pod 的临时存储,并将设备挂载在集群的共享存储中。我们通过 K8s Pod 实现这种架构,重点提供开发机和镜像保存功能,使得开发机更轻便且易于管理。

我们选择这种开发机的设计方式,主要是考虑到大模型研发的需求。在研发过程中,很多开源模型会提供镜像,而大模型的交付环境通常都是基于镜像的,这使得容器化模式非常适合此类场景。使用容器模式可以直接利用现有的镜像,而不需要额外安装 Docker 或进行透传,简化了环境配置。
此外,独占单卡会产生大量碎片化资源。研发人员可能需要频繁切换模型,每次都需要创建独立的开发机。如果采用独占模式,资源碎片化严重,尤其在多卡部署时,这样的资源使用效率低。共享多卡的模式能更好地支持灵活调度和调试。
考虑到我们的集群环境比较混杂,且不是每个集群都有很完善的基础设施,因此无法为每个集群都提供专门的块存储设备池。为保证平台能够提供一个稳定的抽象,我们没有使用块存储来持久化用户数据。开发机中的数据在关闭后会丢失,若需要保存数据,用户只能通过镜像保存功能将环境保留。我们认为这是合理的,因为开发机本质上不应存储数据,数据应该存储在共享存储中,而开发机的核心任务是作为模型开发和调试的环境。
总的来说,我们的开发机抽象设计旨在提供灵活、便捷的开发环境,同时确保平台的稳定性和资源使用的高效性。
平台功能 2:训练任务抽象
训练任务的抽象设计与常见的任务调度模式大同小异,核心在于实现了任务队列的调度管理。我们采用了 Gang Scheduling 机制,确保调度的任务要么全部不调度,要么能够同时调度到位。为了提高资源分配效率,我们还实现了资源超卖策略,进一步优化了资源的整体利用。
此外,借助 Dragonfly 以及多级缓存架构的设计,在集群内部实现了基于 P2P 的镜像分发功能,解决了大规模任务提交时的效率问题;
例如,在开发机上跑完一个 8 卡训练任务并保存为镜像后,使用该镜像在本集群内提交一个 256 台机器的任务。如果没有 P2P 分发,拉取镜像的时间可能超过一个小时,而通过 P2P 分发,镜像拉取速度得到了显著提升。
此外,基于多级缓存的设计,保存镜像时除了向中心存储上传数据,还会同时加载到本集群 的自建存储中作为一级缓存;同时在各个集群的逻辑上层,还设有统一的 Gateway 集群,缓存从互联网拉取的镜像,作为二级缓存,如果集群内没有查询到所需要的镜像,会穿透到二级缓存拉取。
通过生产环境的上线前后对比,20G 以上镜像拉取效率提高 3 倍以上。随着集群内任务规模的扩大、节点数的增多,效率提高更显著,截止目前任务启动成功率 100%。
在任务管理方面,我们重点关注了任务的状态通知。从任务排队到开始运行,再到结束,我们与飞书等平台深度集成,提供实时通知功能,确保团队成员能够及时掌握任务进度。对于多人协作的任务,我们还可以将任务状态通知到团队的群聊中,平台的机器人会自动拉取任务信息,并向群成员发送更新。
为了实现无人值守的训练流程,我们还设计了任务的自动重试策略,确保任务在出现问题时能够自动恢复。

平台功能 3:推理服务
推理服务的需求是将训练好的模型快速部署、测试和评估。推理架构相对简单,主要由两个部分组成:网关和模型。模型层负责负载均衡,启动多个模型实例,可能是 TGI 或者 vLLM 实例,然后进行负载均衡。网关层通过镜像启动,处理格式转换和策略调度等任务。
最终,推理服务通过一个 VIP 对外暴露,确保训练集群和评测集群之间的网络互通。评测集群可以直接通过 VIP 接入进行模型评测,从而加快整个迭代流程。
平台功能 4:数据处理任务抽象
在推理服务发现后,我们注意到很多用户除了部署模型外,还需要处理数据。例如,用户可能需要对一批数据进行处理,比如使用模型对数据进行改写。然而,传统的推理服务抽象并不适合这种需求。推理服务通常是一个固定的服务,比如如果需要 32 张卡,它就会扩展到 32 张卡,再扩展到 64 张卡,而这类固定抽象并不适用于数据处理任务。
数据处理任务的抽象与此不同。我们设计了一个数据处理任务队列,任务会分配给每个 Worker 进行处理。每个 Worker 处理完任务后会结束,从而释放资源。这意味着,处理完成后,资源不会被占用,避免了在传统推理服务中无法释放资源的问题。例如,如果有 1000 张卡用于视频特征提取,传统方式可能会导致长尾任务占用资源,资源长时间无法被释放。
因此,我们的设计专门针对模型数据处理、特征提取等流程和 pipeline 场景,提供了一种数据处理任务抽象,确保资源高效利用并避免不必要的资源占用。
平台保障:多项关键策略确保稳定性
为了确保训练的稳定性,我们采取了三项主要措施,这些措施涵盖了常见的故障处理和任务恢复需求:
故障主动检测与封禁:我们使用 Node Agent 主动监控并检测常见故障,包括驱动版本、GPU 数量、电源风扇告警、共享存储挂载等问题。节点故障检测还涵盖了 GPU 的 XID ECC 错误、路由问题、网络抖动等情况。如果发现故障,系统会自动封禁该节点,避免调度到故障节点上。
任务自动重试机制:训练任务通常是以任务形式提交的。如果任务因为 GPU 故障而失败,系统会自动重试,并且由于坏节点已被封禁,新的任务会分配到健康的节点,确保任务能够自动恢复。这种自愈机制在大多数情况下能确保任务的稳定执行。
任务挂起(hang)与慢速报警:对于一些特殊情况,比如训练速度、GPU 功率突然下降等,虽然这些问题不会直接导致任务挂掉,但可能会影响训练效果。在这些情况下,我们会通过条件检测识别异常并向用户发出告警。用户可以根据告警信息进行人工干预,避免问题进一步恶化。
通过以上这三项措施,我们能够有效保证预训练的稳定性,以一个训练任务的生命周期为例,:
训练任务在我们平台内申请通过后,调度器从可使用 Pool 中分配节点,随后智能筛查服务会使用 NCCL 对这些节点进行高性能网络测试和 GPU 状态探测,确保环境稳定可正常启动训练任务;否则重新分配节点,并将探测不通过的节点放入备池。
训练任务正常启动后,Node Agent 会实时监控、检测节点的状态和训练任务的进程;主动感知训练过程中是否存在降速、抖动以及容器内掉卡等异常;并主动感知 GPU 的 XID ECC 等异常,并识别异常类型针对性 callback 修复流程。
对于训练过程中存在问题的节点,智能筛查会在训练结束后根据 Node Agent 的 callback 进行再次筛查,并根据结果反馈给运维、机房,提起工单自动化报障、维修流程。
虽然大部分故障可以通过主动检测来发现,但仍然存在一些极端情况下,训练任务由于未知原因无法启动。在这种情况下,所有已知的方法都无法解决问题,这时我们只能退回最原始的故障排查方式——二分查找。例如,如果我们有 100 个节点,发现无法启动训练任务时,可以将这些节点分为前 50 和后 50,逐一测试。
为了更高效地解决这个问题,我们开发了智能筛查功能,将这一过程自动化。通过智能筛查,系统能够主动检测并筛选出问题节点。筛查流程如下图所示:

在实际应用中,我们使用两两分组的方式进行筛查。通过对每一组节点运行 NCCL 测试,若发现某一组特别慢,基本可以确定其中有一个问题节点。通过奇偶轮换的方法,我们逐步锁定问题节点。
通过这种智能筛查方法,我们能够高效地识别和排除问题节点,确保训练任务在稳定的节点上运行。即使无法完全分析故障的原因,这种自动筛查功能也能保证节点在端到端训练中表现符合预期,从而解决大部分复杂故障问题。
4
稳定期:从各集群独立存储到构建中心化存储架构
随着平台功能的不断迭代和完善,进入了稳定期。此时,团队人数大幅增长,使用机器学习平台的研发人员数量增加到 200 多人。同时,集群数量从 3~5 个增加到 10 个以上。
在前期易用性和稳定性问题基本解决的情况下,当前的主要关注点转向了资源使用效率和整体资源利用率的提升。例如,当我们新增一个集群时,如何快速进行冷启动,除了前期的基础配置,还需要下载所有相关数据才能开始训练。如果数据无法在集群之间流动,跨集群调度就无法顺利实现,手动拷贝数据既麻烦又低效。
因此,数据流转成为这一阶段的核心瓶颈。单一集群下不存在这个问题,但在多云、异构、混合的复杂环境中,数据流转和调度的优化显得尤为重要。
存储发展历史
在数据存储的发展历程中,最初我们采用了机器上的 NVMe 盘去构建 Ceph 存储系统,最大规模达到 2000 多个盘,裸容量为 8PB。选择这种方式的原因在于搭建速度较快,因为有些集群在初期并未提供商业存储资源,与商务沟通较为繁琐,使用机器上盘的方式可以快速启动训练,避免了依赖其他团队。
Ceph 的另一个优势是其与 Kubernetes CSI 的兼容性非常好,完美支持 quota 等功能。由于平台上的个人卷抽象是基于 K8s PVC 的,我们需要通过 quota 来限制用户存储,防止超标。
最初,我们用 Ceph 主要支持普通的预训练任务,读写压力较小。然而,随着多模态数据的引入,问题逐渐显现 。特别是文件数量激增后,存储系统变得非常不稳定,数以亿计的小文件导致性能急剧下降,系统常常卡住。遇到这种情况,我们几乎只能通过将数据迁移到其他存储来解决问题。
此外,由于我们使用的是 GPU 节点构建的 Ceph 存储,在不稳定的 GPU 环境下,管理 Ceph 存储变得特别复杂,运维成本非常高。比如,Ceph 使用三副本存储,如果刚好三副本中两个副本所在的 OSD 节点同时宕机,整个 Ceph 系统会卡住,而且影响面会很大。我们曾遇到过几台节点被误下线,导致少量的一些 OSD 下线,但由于 Ceph 的数据是打散存储,进而影响了大量数据的稳定性,特别是一些 checkpoint 数据损坏,导致大量数据丢失。在不稳定的 GPU 环境中自建 Ceph 存储的运维成本过高,且很难有效管理。
在中期,我们全面转向采用高性能商业化存储解决方案,如 DDN、GPFS 等。这些传统高性能商业化存储的主要优势是性能高、运维简单。然而,我们也遇到了一些问题。
首先,这类商业存储的价格较高,且供货周期较长,有时扩容需要 1 到 2 个月。
另一个主要的劣势是它们的 CSI 兼容性不理想。例如,GPFS 的 CSI 兼容性不好,特别是在处理 quota 时存在问题,导致即使我们启用了 quota 功能,但在 GPFS 卷上并没有满足业务预期。这使得平台出现了“某用户填满文件系统,导致其他任务挂掉”的问题,且无法通过常规方式解决。解决方案可能需要在 GPFS 上再加一层额外的存储管理系统,但这会导致性能下降,得不偿失。
尽管这些传统商业化存储在性能和运维上有明显优势,但它的兼容性和成本问题仍然是我们面临的挑战。
从集群独立存储到统一中心存储
最初,在我们的架构中,每个集群有不同的用途,如训练集群、推理集群等。它们都有自建的存储系统,数据准备要在各个集群的存储系统间迁移数据,且大量依赖人工操作,过程繁琐又效率低下,往往都要持续几天,且极容易出错。

为了解决这个问题,我们逐步引入了统一的中心存储解决方案。 具体来说,我们在公有云上建立了一个中心存储,通过专线连接所有集群(包括训练集群和推理集群),确保集群之间的数据可以无缝对接。这样,每个集群都能访问到一个统一的命名空间。 例如,A 集群训练好的 checkpoint 可以直接在 B 集群中访问,无需额外的拷贝操作。
通过这个跨集群的统一存储方案,所有集群的数据共享变得更加高效,且实现了类似 K8s 卷的跨集群挂载,使得任务提交和数据访问变得更加便捷。
使用 JuiceFS 构建中心存储
虽然中心存储方案看起来非常理想,但实际实现起来仍然有不少挑战。经过调研,我们最终选择了 JuiceFS 来构建我们的中心存储。JuiceFS 提供了优秀的镜像文件系统和镜像写入能力,适合我们的需求。

我们中心存储的架构是这样组织的:
公有云对象存储:所有资源都存储在公有云上的对象存储中,我们通过专线连接公有云和集群。每个集群之间都通过 100G 专线进行连接。考虑到稳定性问题,目前我们采用主备 100G 专线来确保可靠性。
镜像文件系统:主文件系统位于公有云上,在集群内部署 JuiceFS 的镜像文件系统,镜像文件系统部署在 200G 的存储网上,这大大提高了访问速度。
分布式缓存:使用 JuiceFS 提供的独立分布式缓存组。我们将 GPU 节点上的 NVMe 盘用在分布式缓存,能够提供 PB 级别的缓存。相比原来用这些 NVMe 盘来构建 Ceph 集群的方案,缓存数据本身是不怕丢失的,即使缓存盘的节点故障,只需要从中心存储上重新拉取数据。另外 Ceph 使用三副本存储,而分布式缓存使用单副本存储,意味着 分布式缓存的容量会更大,甚至超过集群中传统商业存储的缓存容量。
支持多协议访问的统一命名空间:完全兼容 POSIX 和 S3 协议的数据访问支持,同时满足机器学习平台数据 Pipeline 的高性能处理和研发人员管理数据的便捷性。
我们使用 JuiceFS 的整体逻辑是,将源集群部署在公有云,其底层数据存储在对象存储上。JuiceFS 采用的是元数据与数据分离的架构。我们在镜像集群内部署了元数据的镜像。通过一系列同步策略和写入策略,确保数据的强一致性。这意味着,当用户在任意一个集群修改数据时,在写确认后,其他集群可以立即看到更新,从而实现了跨集群的统一命名空间。 另外,JuiceFS 支持几乎所有的公有云对象存储,同时也支持如 Ceph、MinIO 等开源和兼容 S3 协议的商业私有化对象存储,借助 JuiceFS 可以帮助业务层屏蔽各个集群自建的底层存储的异构性,实现统一、多融合的中心存储管理。
我们对存储性能进行了测试,发现整体表现不错。在单进程写入性能上,表现比较理想,能够满足需求。对于读取性能,主要有冷读和热读两种情况:
冷读:是指当数据不在集群的缓冲区内时,而通过专线回源对象存储。冷读性能虽不如本地存储理想,但在实际应用中已经足够满足需求。
热读:热读性能表现出色,基本可以与本地的高性能商业存储持平。

根据我们的经验,存储性能不必追求极致,只要确保训练数据读取不成为瓶颈即可。过度追求单点性能可能导致缓存雪崩。 例如,我们曾通过激进的预读调优,使单节点达到了 100+GB/s 的吞吐量,但过多的读取线程导致缓存崩溃,致使很多缓存组节点失联,最终出现雪崩现象,反而需要 GPU 节点回源对象存储影响读取性能。因此,我们决定不再追求单节点的极限性能,而是通过多个节点聚合来充分利用专线带宽。实际训练场景通常是多机训练,单机性能并非关键,确保专线带宽的充分利用即可满足需求。
在机器学习平台的集成过程中,我们发现使用 JuiceFS 非常方便,其中一大优势在于其完善的 CSI 驱动。不同于其他传统商业存储,JuiceFS 的 CSI 驱动非常完善,能够无缝对接我们的平台资源体系,支持跨集群的云个人卷概念。 这样,如果任务只使用云个人卷,数据就能够在不同集群之间无缝调度。
此外,它的 quota 配置还是非常完善的,而且它有非常及时的统计信息,甚至可以实时显示例如一个 300TB 的卷已经使用了 167TB,占比 55%。同时,我们还可以限制文件数量,因为过多的文件会带来管理压力。因此,我们可以设置文件数量的限制。整体而言,这些功能使得存储系统能够非常友好地与我们的机器学习平台无缝集成。
这个中心存储架构,给我们带来了如下优势:
减少单个集群本地存储容量的硬性要求:在大规模数据处理中,尤其是多模态应用,数据量通常达到 PB 级别。传统的分散集群架构需要将数据拷贝到各个集群进行访问。采用 JuiceFS 的中心存储架构后,用户几乎无需感知数据存取过程,能够方便地使用数据,避免了传统方式中数据频繁拷贝的开销。
有效利用 GPU 节点本地磁盘:GPU 节点通常带有多个 NVMe 硬盘,由于节点本身的故障率较高,传统的分布式存储方案(如 Ceph)容易导致存储集群频繁故障,造成较差的可用性。在新的架构中,数据存储于对象存储,NVMe 盘资源用于数据缓存,从而显著提升数据访问效率。
便于集群迁移:训练任务可以在新集群直接启动,无需额外的数据准备。数据访问会在中心存储和集群本地的分布式缓存中透明路由,集群加载数据在从中心对象存储上下载过程中会自动加载到集群本地的分布式缓存中,下一次访问时,数据读取直接命中本地分布式缓存,从而加速数据读取效率。
多集群大一统调度:未来,我们计划实现多个集群的大一统调度,将多个集群整合为一个开发环境,通过集中调度最大化资源利用率,从而提升整体架构的效率。
5
总结
在发展的初期,我们专注于系统稳定性,快速利用现有机器资源,推动模型的研发和训练。在扩张期,我们通过标准化抽象屏蔽了复杂的异构细节,提升了平台的易用性,进一步支持了高效的模型研发。而在成熟期,我们解决了存储和数据流转的核心难题,优化了跨集群的数据管理和调度,提高了整体资源利用率。随着系统的不断完善,中心存储架构的引入使得大规模数据处理变得更加高效。
关于作者
曾奥涵,智谱 GLM 基座模型 & 训练基础设施负责人,作为主要开发者参与了 GLM-130B、ChatGLM、GLM-4 (All Tools)、GLM-4-Plus、GLM-4-Voice 等模型或系统的研发。



4000520066 欢迎批评指正
All Rights Reserved 新浪公司 版权所有