logo

大模型微调退出码 -9 与 -11 的定位及处置实践

作者:暴富20212026.11.06 20:04浏览量:1

简介:在大模型微调中,进程被系统强制终止或触发段错误,往往不是模型代码本身的问题,而是资源分配、CUDA 运行时与训练框架不匹配所致。本文围绕微调过程中稳定复现的退出码 -9 与 -11 展开,分析其背后的内存不足、显存峰值、OOM Killer 以及 GPU 驱动与 CUDA 版本兼容性问题,并给出从现象定位到参数调整、从环境重建到硬件适配的完整排查路径,帮助读者减少无效试错,快速恢复训练任务。

一、问题背景与实验动机

在大模型微调任务中,随着样本规模的增长和超参数组合的增多,我们往往需要反复调整训练配置以观察模型效果变化。本次实验中,样本量已达到约 1.2 万条,此前一直采用分布式训练中的某类显存优化策略进行训练,整体过程相对稳定。近期在查阅关于多模态模型微调的资料时,注意到一种观点:当单卡显存足够时,应优先选择显存占用更高但通信开销更低的优化级别,而不是默认使用将模型参数切分到多卡的高压缩级别。

为了验证这一观点在大语言模型微调场景中是否成立,我们设计了一组控制变量实验,仅调整分布式训练中的优化级别,其余数据、模型、训练轮次、学习率等条件保持不变。然而,在将优化级别从更高压缩档位切换到较低压缩档位后,训练任务连续出现两类非典型退出错误:退出码 -9 和退出码 -11。由于这两类错误均缺乏完整的异常栈信息,排查难度显著高于常规的显存溢出报错。

本文将依次说明这两类错误的现象、触发条件、底层原因以及对应的解决方案,并总结出一套可复用的排查流程,供同类微调任务参考。

二、退出码 -9:进程被系统强制终止

2.1 错误现象

在将分布式优化级别从模型参数切分模式切换到仅优化器状态切分模式后,训练任务在模型检查点保存阶段稳定出现退出码 -9。该错误的表象是进程直接消失,日志中没有任何 Python 异常栈,也没有 CUDA 显存溢出的详细提示,仅在调度系统中显示任务被终止,并返回错误码 -9。

2.2 初步定位思路

退出码 -9 在 Linux 系统中的含义比较明确:进程收到 SIGKILL 信号,被操作系统强制终止。与普通的 Python 异常退出不同,SIGKILL 无法被程序捕获,因此不会留下应用层的报错信息。常见触发来源包括:

  1. 用户主动执行 kill -9;
  2. 任务调度系统因为超限或策略原因强制终止进程;
  3. 操作系统 OOM Killer 因为系统可用内存不足,选择终止占用内存较高的进程。

结合训练任务的运行环境,前两类原因可以基本排除。任务并非手动终止,调度系统也未显示资源超限的策略性终止记录。因此,排查重点落在系统内存不足这一方向上。

2.3 为什么更换优化级别后内存会暴涨

要理解内存暴涨的根因,需要先明确两种分布式优化级别的核心差异。

在高压缩级别下,模型参数会被切分到所有参与训练的 GPU 上。这意味着每张 GPU 只保存模型参数的一部分,通常为参数总量的 1/n。与之相对,较低压缩级别只对优化器状态进行切分,模型参数会在每张 GPU 上完整加载。因此,从显存角度看,较低压缩级别下每张 GPU 的模型参数占用会显著上升;从系统内存角度看,保存检查点时也会引入额外的峰值压力。

保存检查点的过程中,分布式训练框架通常会在系统内存中构造一个完整的模型权重副本,用于后续的聚合和写入磁盘。这个临时副本的大小与完整模型权重相当,在模型规模较大时可能高达数十 GB。若每张 GPU 所在节点配置的系统内存为 64 GB,同时运行多个进程或其他训练中间变量也占用内存,则保存检查点时构造完整权重副本的操作很容易触发系统 OOM。

本次实验中,错误稳定出现在检查点保存阶段,与上述推断高度一致。

2.4 解决方案与验证

为验证内存不足这一推断,我们重新申请了系统内存更大的 GPU 节点进行测试,将每张 GPU 对应的系统内存从 64 GB 提升到 128 GB。在保持其他训练配置完全不变的情况下,训练任务顺利通过检查点保存阶段,退出码 -9 不再出现。

这一结果证实了问题根因:较低压缩级别在保存检查点时会在系统内存中构造完整权重副本,当节点内存不足时触发 OOM Killer,导致进程被强制终止。因此,在切换分布式优化级别时,不仅要评估显存是否足够,还必须评估系统内存的峰值占用,尤其是在模型规模较大且需要频繁保存检查点的场景中。

2.5 补充建议

对于系统内存有限的场景,可以考虑以下缓解措施:

  • 降低检查点保存频率,减少峰值内存压力的出现次数;
  • 在保存前主动清理不必要的中间变量或缓存;
  • 通过环境变量或配置项调整检查点保存策略,避免在单一节点上聚合完整权重;
  • 若条件允许,为训练节点配置更充足的系统内存,或选择内存与显存比例更均衡的硬件规格。

三、退出码 -11:段错误与运行环境不匹配

3.1 错误现象

在解决退出码 -9 问题后,为了获取更新版本的训练框架特性,我们重新拉取了最新代码仓库,并基于新建的独立 Python 环境重新安装依赖。随后再次运行训练脚本时,出现了退出码 -11 的报错。

退出码 -11 对应 Linux 系统中的信号 11,即 SIGSEGV,段错误。段错误意味着进程试图访问不允许访问的内存地址,常见原因包括空指针解引用、数组越界、访问已释放内存、栈溢出,以及底层库与运行时环境不兼容导致的内存布局异常等。

3.2 排查过程

在新建环境中,安装命令大致如下:

  1. conda create -n train_env python=3.11
  2. pip install -e ".[torch,metrics]"
  3. pip install deepspeed

安装过程本身没有报错,所有依赖均正常解析并完成安装。但运行训练脚本时,段错误几乎在启动后立即出现,而不是运行到某个特定训练步骤才触发。这一现象提示问题可能不在训练代码本身,而在于环境中的底层库之间存在不兼容。

进一步检查环境中安装的深度学习框架版本时发现,通过最新代码仓库自动解析安装的 PyTorch 版本为 2.9.1,并且对应 CUDA 运行时版本为 12.8。然而,当前 GPU 硬件的驱动所能支持的最高 CUDA 运行时版本仅为 12.1。

3.3 根因分析

当深度学习框架编译时使用的 CUDA 运行时版本高于 GPU 驱动实际支持的版本时,框架在初始化过程中会尝试加载更高版本的 CUDA 库或调用不被当前驱动支持的接口。这种不匹配不会总是表现为明确的版本错误提示,而是在底层内存管理、上下文创建或内核启动阶段引发非法内存访问,最终表现为段错误。

这类问题在升级训练框架或重建环境时尤为常见。原因在于,包管理器默认会安装最新的二进制发行版,而这些发行版通常针对较新的 CUDA 版本构建。如果硬件驱动未能同步升级,就很容易出现运行时版本高于驱动支持上限的情况。

3.4 解决方案

解决该问题的核心思路是让深度学习框架的 CUDA 版本与 GPU 驱动支持的范围对齐。具体操作如下:

  1. 查询当前 GPU 驱动支持的最高 CUDA 运行时版本;
  2. 卸载当前安装的高版本深度学习框架及其相关 CUDA 依赖;
  3. 重新安装与硬件支持版本相匹配的深度学习框架版本;
  4. 重新安装分布式训练相关的扩展库,确保其与所选深度学习框架版本兼容;
  5. 验证新环境下 CUDA 运行时版本与驱动是否匹配。

在本例中,将 PyTorch 从 2.9.1+cu128 更换为兼容 CUDA 12.1 的版本后,段错误消失,训练任务恢复正常。

3.5 环境复现注意事项

在团队协作或多机训练场景中,同一套环境配置可能需要在不同硬件上运行。不同 GPU 型号和驱动版本对 CUDA 运行时的支持上限不同,因此在分发环境配置或编写安装脚本时,应当注意以下几点:

  • 避免在安装脚本中硬编码某个具体版本,而是先检测目标机器的驱动与硬件能力,再决定安装哪个版本;
  • 在重建环境前,优先确认现有驱动版本与待安装框架版本的兼容性;
  • 保留环境构建日志,便于在出现段错误等无明确报错的异常时快速回溯版本组合。

四、两类错误的对比与排查方法论

退出码 -9 和退出码 -11 虽然都表现为进程异常终止,但触发机制和排查路径有明显差异。

退出码 -9 通常与资源限制直接相关,尤其是系统内存不足或显存耗尽导致的 OOM Killer 行为。这类问题的特征包括:错误发生时机相对固定,例如总是在保存检查点、加载数据或某个特定训练阶段触发;日志中没有应用层异常栈;增加资源配额后问题通常可以消失。

退出码 -11 则更倾向于环境不匹配或底层库缺陷。它的出现往往与某个依赖的版本变更、驱动与运行时不一致、编译器选项不兼容等因素有关。排查时应当优先检查环境变更历史、依赖版本组合以及硬件与软件的支持矩阵。

在实际工程中,推荐按照以下顺序进行排查:

  1. 确认错误码的具体含义,判断是资源类问题还是内存访问类问题;
  2. 检查任务日志,定位错误发生的具体阶段,是启动阶段、训练阶段还是保存阶段;
  3. 分析该阶段的资源占用特征,评估是否存在内存或显存峰值;
  4. 检查最近的环境变更,包括依赖升级、配置修改、硬件调整等;
  5. 通过小规模实验或环境回滚验证推断。

五、总结

本次实验的初衷是验证不同分布式优化级别对模型效果的影响,但在切换配置的过程中,先后遇到了退出码 -9 和退出码 -11 两类非典型错误。通过分析错误码含义、结合训练阶段特征与资源占用情况,成功定位到保存检查点时的内存峰值问题以及环境重建时的 CUDA 版本不匹配问题,并通过增加系统内存和回退框架版本分别解决。

这两类问题的共同点在于:错误信息不直观,容易让人误以为是模型代码或训练数据存在问题。实际上,在分布式大模型微调中,相当一部分异常来自资源评估不足和环境配置不当。掌握退出码的含义、熟悉训练各阶段的资源占用特征、建立环境变更台账,能够显著提升问题定位效率,减少无效重试。后续在开展类似的控制变量实验时,也应当将系统内存、驱动版本、深度学习框架版本等因素纳入统一考量,避免因基础设施层面的干扰影响实验结论的可靠性。

发表评论

活动