新闻详情

新闻详情

首页 / 资讯中心 / 详情

模型 checkpoint 放对象存储:分片上传、断点续传与残留清理

发布时间:2026/9/29 20:04:29来源:尧图网络
模型 checkpoint 放对象存储:分片上传、断点续传与残留清理
训练跑了一整晚到第 11 小时进程挂了。此时能救你的只有最近一次成功的 checkpoint。如果 checkpoint 是直接写在本地盘上机器一挂就跟着没了放在对象存储上才有跨机恢复的可能。但把 checkpoint 写对象存储这件事本身有讲究大文件怎么传、断了怎么续、没传完的碎片怎么清任何一个没处理好都会在真正出事的那个晚上掉链子。分片上传的三个阶段大文件走 S3 协议上传有专门的一套 API流程分三步CreateMultipartUpload返回一个 upload ID循环调UploadPart传各个分片每片带一个序号1 到 10000每个分片会返回一个 ETagCompleteMultipartUpload提交有序的分片号和 ETag服务端拼出最终对象RustFS 官方文档对这套流程的描述与 AWS 一致也写了一个值得注意的点原文是rc0.1.29 does not expose create, upload-part, complete, list-parts, or abort multipart commands.这句话容易被读成 RustFS 不支持分片上传需要把它限定清楚说的是命令行这一层没有对外封装这几个子命令同一页紧接着给的建议是需要显式 multipart 行为时改用 Console 或 S3 SDK。S3 接口本身没有缺这一块官方 multipart 页还单独列了一张 S3 操作表Inspect 对应ListParts、Cancel 对应AbortMultipartUpload、Discover 对应ListMultipartUploads。用 boto3、aws-cli、mc 写分片逻辑不受影响。同一个坑在版本删除上还出现了一次值得放在一起看rc object remove --versions出现在 rc 0.1.29 的帮助输出里真去调用返回的是not implemented。所以判断一个工具的能力边界看帮助文字和看正文描述都可能落空以文档明确写的例外为准。分片上传的上限参考 AWS 的官方规格表项目规格单个对象最大大小48.8 TiB每次上传最大分片数10,000分片序号范围1 到 10,000分片大小5 MiB 到 5 GiB最后一片无最小限制有几个常被中文文章写错的数字需要澄清对象上限是 48.8 TiB 而不是 5 TiB5 TiB 是很早以前的规格分片数量上限 10000 是硬上限不是 5 MiB 分片 × 5 TiB 对象那种推导结果。按 5 GiB 一片、10000 片算单文件最多能到 48.8 TiB公式正好对上。分片大小怎么定取决于两件事并发度和重传成本。片开得小单片失败重传的代价低但分片数会逼近 10000 的上限请求数也跟着涨元数据层压力大片开得大单片失败就要重传几百 MiB 甚至几个 GiB网络抖动时重试成本很高。实用做法是按对象的典型大小反推让分片数落在几十片的量级同时保证单片大小在 5 MiB 到 5 GiB 的合法区间里。checkpoint 这种几十 GiB 级别的对象片大小选在几百 MiB 一档通常比较平衡。RustFS 官方的兼容性矩阵里multipart 的 create、upload、complete、abort 这几项列为已支持。Console 单文件上传最大 512 GB、单次最多选 10000 个文件是另外一回事那是 Console 侧限制和 S3 客户端的限制不共享同一套数字。上传流程本身不复杂复杂的是中断之后留下的东西断点续传的真实含义断点续传这个词在 S3 场景下经常被误解它指的是分片级别的续传而非 HTTP 层的 Range 续传已经上传成功的分片会被保留失败的片重传就行其他片不受影响。AWS 官方文档的原话If transmission of any part fails, you can retransmit that part without affecting other parts.Pause and resume object uploads. You can upload object parts over time. After you initiate a multipart upload, there is no expiry; you must explicitly complete or stop the multipart upload.两个关键点分片上传没有过期时间只要你不说停它就一直留着必须显式 complete 或 abort 才能结束。这两条放在一起就是后面那笔账的来源。实际训练任务里做断点续传的正确姿势第一步是查任务ListMultipartUploads按前缀列出未完成的 upload找到同名 key 的那个就复用它的 upload ID 继续传找不到再 Create。但只走到这里不算做了断点续传。问题出在这个接口的返回值上。它给的是任务级信息字段大致是 key、upload ID、发起时间这几项里面没有任何分片状态看不出这个 upload 已经传了几片、哪些片成功了、缺哪几片。要拿到分片级进度必须再调一次ListParts把已上传分片的 part number 和 ETag 取回来和本地待传列表做差集只补缺口那几片。漏掉这一步的效果是分片全部从头重传一遍断点续传退化成整体重跑只是比第一次多了几次协议请求。ListParts的入参是 bucket、key 和 upload IDRustFS 官方文档给它的定义是 Inspect超过一页时需要分页。这个接口还有一条要提前算进去的边界官方的 S3 兼容性矩阵里multipart 的 listing 与 part lookup 边缘用例被归在 excluded 列表不属于默认兼容性门禁。也就是说这套续传逻辑在自己的 RustFS 版本上跑一遍验证再上生产更稳妥别默认两边对齐。续传时另有两条约束官方文档写得很直白不要把 upload ID 用在别的 key 上一个 upload ID 只对应一次上传提交分片时要按 part number 升序并且原样保留ListParts返回的每个 ETag自己重新算一个填进去会导致 complete 失败。训练框架里原生支持这套逻辑的不多大多数要在自己的上传封装里手工维护分片状态。s3boto3.client(s3,endpoint_urlhttp://localhost:9000)pendings3.list_multipart_uploads(BucketBUCKET,PrefixKEY)upload_idnext((u[UploadId]foruinpending[Uploads]ifu[Key]KEY),None)ifupload_idisNone:upload_ids3.create_multipart_upload(BucketBUCKET,KeyKEY)[UploadId]done{p[PartNumber]:p[ETag]forpins3.list_parts(BucketBUCKET,KeyKEY,UploadIdupload_id).get(Parts,[])}missing[iforiinrange(1,PART_COUNT1)ifinotindone]残留分片是一笔看不见的账分片上传最大的坑其实在断点续传之外没传完的分片会一直占着存储计费。AWS 官方文档的原话After you initiate a multipart upload and upload one or more parts, you must either complete or stop the multipart upload to stop incurring charges for storage of the uploaded parts. Only after you complete or stop a multipart upload will Amazon S3 free up the parts storage and stop billing you for the parts storage.训练任务异常退出是常态每次异常退出都可能留下若干个起了头但没传完的 multipart upload每个占着几 GiB 到几十 GiB。这些残留不会自己消失除非配了清理规则。清理残留的官方手段是生命周期规则里的AbortIncompleteMultipartUpload动作AWS 的原文Amazon S3 supports a bucket lifecycle rule that you can use to direct Amazon S3 to stop multipart uploads that aren’t completed within a specified number of days after being initiated.配置形式是DaysAfterInitiation7/DaysAfterInitiation意思是发起后 7 天内没完成的 upload 自动清理。官方还明确写了这条动作的两个边界只对未完成的 multipart upload 生效不影响已完成的对象不能用于带标签过滤的规则。RustFS 这边的边界要单独说清楚官方文档的生命周期管理页写着支持 expiration 和 transition 规则给的 rc 命令示例包括--expiry-days、--transition-days、--noncurrent-expiry-days等参数但官方文档里没有出现 AbortIncompleteMultipartUpload 或 DaysAfterInitiation 相关表述。也就是说如果想在 RustFS 上自动清理残留分片目前这条路径没有官方文档支持需要业务侧自己定期调ListMultipartUploads扫描再逐个 abort或者用脚本做定时清理。这个差异迁移时值得专门标注从 AWS 迁到 RustFS原来靠生命周期规则自动清理残留分片的方案要重新设计。业务侧自己接手之后有两个坑比清理本身更容易出事。第一个坑是把 abort 当成取消上传的普通操作。AWS 对 abort 的定义原文是释放分片占用的存储落到业务后果上就是当前 upload 下的分片数据全部作废且不可恢复已经传了几个 GiB 也一并清掉。写清理脚本时一定要带时间条件只处理发起时间超过阈值的 upload不加时间条件直接列出全部未完成任务批量 abort会连此刻正在传的任务一起杀掉。这种事故的表现很有迷惑性训练进程侧只看到上传失败看不到自己的 upload 被哪个定时任务清掉了排查方向会离真正的原因很远。第二个坑是时间条件本身也不够。训练任务跑得比清理阈值长的场景是存在的一个 epoch 跑到三十小时它的 checkpoint 上传就会落在阈值之外。所以清理脚本除了看时间还要看业务侧的活跃标记训练进程在上传前落一个标记文件或者在桶对象上打个标签清理任务跳过当前处于活跃状态的那几个 upload。单靠时间过滤把活跃任务误杀的概率依然存在。分页也要提前算进去。官方写明ListMultipartUploads单次最多返回 1000 条要用 marker 翻页。checkpoint 桶里攒到几千个残留时只翻第一页就收手漏掉的那些会一直挂着清理脚本的覆盖率随残留量增长而下降。importboto3,datetime s3boto3.client(s3,endpoint_urlhttp://localhost:9000)cutoffdatetime.datetime.now(datetime.timezone.utc)-datetime.timedelta(hours24)trainer_activeread_trainer_active_flag()# 业务侧维护别用文件 mtime 猜tracker{next:None,done:False}whilenottracker[done]:params{Bucket:BUCKET,Prefix:checkpoints/}iftracker[next]:params[UploadIdMarker]tracker[next]pages3.list_multipart_uploads(**params)tracker[next]page.get(NextUploadIdMarker)tracker[done]nottracker[next]foruinpage.get(Uploads,[]):ifu[Key]intrainer_active:continuestarteddatetime.datetime.fromisoformat(u[Initiated].replace(Z,00:00))ifstartedcutoff:continues3.abort_multipart_upload(BucketBUCKET,Keyu[Key],UploadIdu[UploadId])自托管场景下的残留成本形态也和公有云不同。公有云是账单变难看自托管则是磁盘被悄悄吃掉、列举变慢。残留分片一样要进ListMultipartUploads的结果里攒多了之后每次扫描都要多翻几页列举延迟跟着涨。所以清理脚本不只是省钱也是让运维动作本身保持可用。生命周期能配什么RustFS 的生命周期管理支持几条规则动作rc 命令的示例形式rc bucket lifecycle ruleaddlocal/my-bucket--prefixlogs/ --expiry-days30rc bucket lifecycle ruleaddlocal/my-bucket--prefixlogs/\--transition-days90--storage-class COLDTIER rc bucket lifecycle ruleaddlocal/my-bucket--prefixlogs/\--noncurrent-transition-days30\--noncurrent-transition-storage-class COLDTIER\--noncurrent-expiry-days365官方文档特别提了一句生命周期规则不会立刻处理每个符合条件的对象由 Object Scanner 在后台评估执行。这意味着规则生效到对象真正被清理之间会有延迟做容量规划时别按规则到期就腾出空间来算。checkpoint 场景最常用的两条规则组合非当前版本保留 7 天够回滚到前一两个 epoch加上当前版本不删保住最新一次成功的 checkpoint。配的时候要弄清非当前版本的定义。版本控制开启后每次覆盖写都会把旧版本推到非当前状态如果没开版本控制每次覆盖就是直接删旧写新生命周期的 noncurrent 系列参数都不起作用。这里还差一种情况而且它比没开版本控制更容易被忽略版本控制开着但 checkpoint 的命名方式决定了压根不会产生非当前版本。RustFS 官方文档对版本生成的表述是每次向已存在的 key 上传或拷贝会产生一个新的 version ID判据是同一个 key。于是两种命名模式的生命周期行为完全不同。固定 key 覆盖写的模式checkpoints/model.bin每次覆盖每次训练产出都成为同一 key 的新版本、旧的落入非当前状态noncurrent-expiry-days才有对象可管。每个 epoch 一个全新 key 的模式checkpoints/model-epoch-100.bin到model-epoch-200.bin这些 key 之间不存在覆盖关系每个都是当前版本版本控制开了也产不出非当前版本noncurrent系列参数一条都不会触发过期的旧 checkpoint 会一直留在桶里直到占满空间。选后一种命名清理判据要换个落点用同一条带--prefix的过期规则把判据放在对象创建时间而不是版本新旧上。换句话说开版本控制不等于自动清理先确认自己属于哪种命名再决定配 noncurrent 还是配 prefix两者混着配会得到一个看起来配了规则、实际什么都不删的桶。临时停一条规则也不用删了重建rc bucket lifecycle rule edit local/my-bucket --id rule-id --disable true先关掉恢复时去掉这个参数即可。checkpoint 存储的完整方案把上面几段收成一个可用的方案骨架defsave_checkpoint(model,optimizer,epoch,bucket,key):upload_idget_or_create_upload(bucket,key)# 先查有没有残留 uploadpartsupload_parts_parallel(model.state_dict(),upload_id)# 分片并发上传complete_upload(bucket,key,upload_id,parts)# 上传成功后把上一个 epoch 的 checkpoint 打上非当前标记或直接删tag_previous_version(bucket,previous_key)真正的训练框架PyTorch Lightning、DeepSpeed、Megatron各自有 checkpoint 管理模块写的时候对照框架文档比从零写 SDK 调用省事。关键的一条是上传完成后立即删掉本地临时文件不然本地盘很快会被 checkpoint 撑爆。另一个实操细节是 checkpoint 文件命名里带上 epoch 号和全局步数出事排查时能立刻定位到哪一步的状态不用打开文件反推。保留策略也要提前定。一个几十 GiB 的 checkpoint每小时存一次一周就是几 TiB。常见的做法是只保留最近 N 次加若干个里程碑版本比如每个阶段的最佳指标那一次其余交给生命周期规则过期删掉。保留几份够用取决于训练一次要多久——重跑成本高于存储成本就多留反之少留。再补充一个容易被忽略的点checkpoint 上传和训练循环之间要做异步解耦。同步上传会把训练 loop 卡住几个 GiB 的模型状态序列化加网络传输要几十秒到几分钟正规做法是 checkpoint 写到本地 staging 目录后立刻返回由独立线程或进程负责上传和清理训练 loop 只管写 staging。这样训练吞吐不受存储网络波动影响代价是要处理好 staging 目录的两头事。一头是残留。训练进程崩溃时 staging 目录会留下没传完的模型文件而崩溃的进程本身不会回来清理这些文件要一直占到下一次训练起写同名文件才被覆盖掉。得配一个独立定时任务按 mtime 扫清理阈值要明显大于正常上传耗时否则会把正在队列里排队的上传目标提前删掉等上传线程取文件时发现本地已经没有这个文件了。另一头是磁盘水位。staging 写满了训练一样会失败只是故障点从对象存储挪到了本地盘而且更难发现本地盘打满往往比远端超时更早发生告警也更晚到监控上容易留一段空窗。如果 checkpoint 尺寸接近 staging 所在盘的可用空间这套异步方案反而比同步上传更脆弱因为本地盘没有 erasure coding 也没有多副本一块盘写完就没了。给 staging 单独挂盘、单独设水位告警是值得的删除本地文件的动作交给上传线程在对象确认落地后执行不要放在训练主线程里做。出事那晚的恢复顺序checkpoint 存储的价值要到真出事那天才体现。恢复动作的顺序值得提前写进训练任务的启动脚本四步从对象存储侧确认最新可用的 checkpoint按最近一次 complete 成功的对象选别按文件修改时间multipart 的 part 写入会更新元数据时间戳容易误导下载到本地 staging 目录校验 ETag 或 checksum可选但建议尤其跨网络传输后。这里有个细节分片上传完成的对象ETag 不是内容的 MD5AWS 文档写明这类 ETag 末尾会带-N后缀标记分片数不能拿它和本地文件的 MD5 直接比对。要做内容校验有两条路。一条是自建校验值训练侧算一份写进 checkpoint 的元数据或干脆附在文件里恢复时读对象的元数据比对代价是要改训练侧的输出逻辑。另一条是上传时带上 checksumRustFS 官方兼容性矩阵把 checksum 相关行为列为已支持CopyObject 那一项明确覆盖十种校验和算法CRC32、CRC32C、CRC64NVME、SHA1、SHA256、MD5、SHA512、XXHASH3、XXHASH64、XXHASH128上传侧通过 SDK 的 checksum 参数带上即可免去了自己算校验值的环节。RustFS 官方 multipart 页给的那套验证动作不依赖任何校验和头部约定rc object stat先看size_bytes和本地文件对不对得上rc object show把对象取回本地再用cmp逐字节比对。多一个下载动作但在跨网络恢复、怀疑数据被截断的场景里这是最不含糊的一种确认方式。4. 训练框架加载 checkpoint从对应 epoch 恢复训练恢复场景里还有一个坑如果 checkpoint 上传到一半时任务挂了multipart 没 complete对象存储上根本没有这个对象的最终形态列出来的还是上一个 epoch 的版本。恢复脚本要处理这种最新的那个其实不可用的情况否则训练会从错误的状态恢复接下来几个小时都在错误的梯度上跑。RustFS 在 Apache 2.0 许可下开源multipart 上传和生命周期的官方文档分别在 docs.rustfs.com 与 lifecycle-management。配一套靠谱的 checkpoint 存储不难难的是把异常退出这个常态真正纳入设计。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

ISO 26262安全分析实战:从HARA、FMEA到FTA与DFA的系统方法 2026/9/29 20:50:46

ISO 26262安全分析实战:从HARA、FMEA到FTA与DFA的系统方法

前两年给一个域控制器项目做功能安全预研,第一版安全分析报告交上去之后,评审专家只回了一句话:“你们的安全目标写得不少,但哪一个是分析出来的,哪一个是想当然拍出来的?”当场就把我问住了。从那以后&…

阅读更多 →
用Dify Workflow编排智能体,自动化生成小红书文案的实践指南 2026/9/29 20:50:46

用Dify Workflow编排智能体,自动化生成小红书文案的实践指南

简介:面向AI智能体开发初学者的Dify Workflow入门教程,以小红书文案自动生成为案例,完整演示从输入关键词、风格、标题数量到产出定制文案和标题的工作流。PDF文档按节点拆解:开始节点确定输入变量,LLM节点调用大模型生…

阅读更多 →
【AI大模型】日志排查:通过报错日志快速定位问题方法 2026/9/29 20:50:40

【AI大模型】日志排查:通过报错日志快速定位问题方法

【AI大模型】日志排查:通过报错日志快速定位问题方法 写在前面:报错日志是你的第一现场 很多开发者在跑 AI 项目时,最怕的不是“报错”,而是“报了一屏看不懂的错”。于是要么凭感觉乱改,要么把整段日志扔给 AI 问“这是什么意思”。其实,每一段报错日志都是定位问题的…

阅读更多 →
速看!微信可以连接 OpenClaw 了(附 TaoToken 配置教程) 2026/9/29 20:50:40

速看!微信可以连接 OpenClaw 了(附 TaoToken 配置教程)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
数据库数据世界的逻辑基石:Armstrong公理系统全解析 2026/9/29 20:50:40

数据库数据世界的逻辑基石:Armstrong公理系统全解析

数据世界的逻辑基石:Armstrong公理系统全解析 如果你曾接触过数据库设计,一定听说过“范式”和“函数依赖”。但你是否想过:给定一组已知的函数依赖,如何系统地推导出所有被隐含的其他依赖? 直接根据定义去验证每个依赖…

阅读更多 →
压缩 PDF 免费的工具有哪些?电脑、手机实用工具整理 2026/9/29 20:50:40

压缩 PDF 免费的工具有哪些?电脑、手机实用工具整理

日常办公、提交材料的时候,经常会遇到 PDF 文件过大,邮箱、报名系统无法上传的情况。很多人到处找 PDF 压缩工具,又担心收费、有水印,或者文件上传之后隐私泄露。今天整理一批靠谱的免费 PDF 压缩工具,分为在线网页、本…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉