PCCL: 多卡异常问题分析指南(v2.1)
1. 前言
本文旨在阐述在基于 PPU 进行多卡或多节点模型训练时,如何有效处理程序崩溃(crash)与挂起(hang)等异常情况。在分布式训练与推理场景中,NCCL 相关的崩溃或超时是较为常见的故障。本文将为相关开发人员提供一套系统性的故障分析方法,涵盖从初步排查到深度诊断的完整流程。此外,针对复杂的系统挂起问题,本文将详细介绍如何生成并保存 PPU 的执行状态转储(dump)文件,以供平头哥(T-Head)技术团队进行离线分析与问题定位。
后面几节将先从通用的现场分析方法(第二节)开始,再具体稍详细介绍适用于两种不同情况的分析方法,其中包含第三节 crash 现场分析方法以及第四节较复杂的 hang 现场发生时的分析方法。
2. 快速现场初判
本节介绍一套由浅至深的故障分析流程。该流程旨在通过对应用层和系统层的逐一排查,逐步缩小范围并定位故障根源。
2.1 应用 log 分析
在上层应用所报的 log 中我们主要关注 pccl init 阶段的日志信息与上层应用(含框架/模型训练代码)中的Error/Warning等信息。其中通信库的 log 需要应用启动前配置环境变量NCCL_DEBUG 为 INFO 方可显示。
pccl 日志:
关注通信 ranks 间使用的传输类型,一般高效的单机内通信会发生在 ICN 链路上,而高效的多机间通信则会通过 IB 网卡参与的 RDMA 链路来进行。当 logs 中出现其他类型的 path type 时,就需要保持警惕,可以怀疑节点内的 icn link 状态或者节点之间网络是否存在问题。
当发现机内 ICN 连接问题时,在问题机器上使用
ppu-smi topo -m观察机内 topo 是否符合预期。当出现 IB 相关问题时,在问题机器上使用 ib 相关工具检查网络是否正常。
关注 topo 创建的情况。进一步可以通过设置
NCCL_TOPO_DUMP_FILE和NCCL_GRAPH_DUMP_FILE将init 阶段生成的 topo 或 graph dump 到文件中做离线分析。特别地,当任务配置了
NCCL_DEBUG_SUBSYS=ALL或者NCCL_DEBUG_SUBSYS=COLL时,可以请 pccl 团队解析通信 op 的执行序列,以便于后续问题进一步定位。
框架日志中的 Error 情况:
通过检查参与通信的各个进程执行的状态,可以看是否有某 rank 对应的进程或线程提前退出的情况,此时其他 peer rank 对应的进程或线程因某步通信同步未能得到响应一般会陷入 hang 的状态,乃至可能会 timeout 退出。当上述情况发生时,一般需要先检查异常 rank 提前退出的原因。
下面2.1.1 与2.1.2 小节中我们将重点说明下如何得到 pccl 执行时生成 logs 及 关键 topo / graph dump files 以进一步做分析的方法。
2.1.1 pccl topo & graph 分析
配置 NCCL_TOPO_DUMP_FILE=pccl_topo.xml 和 NCCL_GRAPH_DUMP_FILE=pccl_graph.xml, pccl 初始化完成后,会在当前路径生成类似如下的 xml 文件。

topo 文件示意如下,可以检查系统中的 PPU 和网卡连接关系是否符合预期。

graph 文件示意如下,可以检查 ring/tree/fc等算法 topo,以及 typeintra/typeinter 等连接类型是否符合预期。

2.1.2 pccl log 分析
pccl log 分为两部分:init 过程日志和 runtime 过程日志。在开启 NCCL_DEBUG=INFO后,如无其他NCCL_DEBUG_SUBSYS 设置,默认显示部分 init 过程日志。
日志格式:

日志默认打印到屏幕,如果通过配置环境变量,可以选择区分 comm,hostname 和 pid 分别打印到不同的文件中,具体配置方法如下:
如果不需要区分 comm,可以配置 "export NCCL_DEBUG_FILE = xxx-%h-%p.log",那么日志路径为 xxx-hostname-pid.log,%h 和 %p 是可选的,配上后会按照 hostname 和 pid 的不同而分别进行日志文件存放。
如果需要区分 comm,可以配置 “export NCCL_PER_COMM_HASH_DEBUG_FILE = xxx-%c-%h-%p.log”,那么日志路径为 xxx-commHash-hostname-pid.log,ncclCommInitAll 或者 ncclCommInitRank 之前的打印,仍然按照原规则不变:如果没有配 NCCL_DEBUG_FILE,打印在屏幕,配了 NCCL_DEBUG_FILE,打印在对应路径下。
限制:目前当需要区分 comm 来将log 输出到不同文件时,设置 "NCCL_PER_COMM_HASH_DEBUG_FILE" 这种方式只支持一个线程起一个通信 comm 的情况,如果一个线程有多个 comms,所有 comms 的日志都会打印到第一次调用 ncclCommInitAll 或者 ncclCommInitRank 使用的 comms 对应的日志文件。
在默认的日志中,我们主要关心以下信息:
机内 peer 之间是否走到了P2P。(某些异常情况如机器内部发生 icn link down,或者 devices 间没有直接的 icn link 链接时会使用 SHM 或者 PCIE P2P);

跨节点的 peer 之间是否选择了 RDMA,以及是否通过较高性能的 GDR 方式进行 PPU 与 网卡间数据传输;

还有一种特殊情况,即部分节点的 init 日志已经显示完成,但存在一些节点的 init 日志不全,这种情况一般意味某些 rank 因某种原因尚未参与/或部分参与 init。需要定位 host 侧原因。它的出现往往会发生在训练或者推理的第一个 iteration 。
2.2 系统 dmesg -T分析
在 kernel 日志中,我们主要关注 PPU 和 RDMA NIC 相关的错误和报警信息。可通过如下 shell 命令过滤。
dmesg -T | grep IH
dmesg -T | grep Error
dmesg -T | grep mlx5注:需要确保 dmesg 信息的开始时间早于应用启动时间。如果有异常信息,它的发生时间应晚于任务启动时间。
与 PPU 相关的 exceptions 信息类型介绍可见下面文档:PPU XID定义
3. crash 现场分析
crash 主要分为两类,一类是 crash in host ,另一类是 crash in ppu。
3.1 crash in host
建议使能操作系统的 coredump。通过配置ulimit -c unlimited打开。应用 crash 后会在相应的路径下生成host coredump 文件。此时建议用户先 high level 做上层应用逻辑出错排查。当 crash 发生在 PPU 软件栈上时则可联系 PPU 同学协助做排查。
3.2 crash in PPU
3.2.1 现场分析与生成 coredump
PPU 上发生 crash 时, 应用会退出,同时在 dmesg 信息中有日志显示(dmesg -T | grep IH -A2 -B2)。PPU 不会默认生成 coredump,建议使用如下环境变量保存 lightweight 的 coredump。coredump 生成后用户可尝试使用 ppu-gdb 工具进一步做问题排查,复杂的涉及到 PPU SDK 中的 device kernels 出错也可找平头哥同学协助进行排查。
export ALIPPU_ENABLE_COREDUMP_ON_EXCEPTION=1
export ALIPPU_ENABLE_LIGHTWEIGHT_COREDUMP=1
export ALIPPU_COREDUMP_FILE=${HOME}/hggc.core.%h.%p.%t3.2.2 hold 现场不生成 coredump
如果配置生成 coredump 发生 Exception 的 device 会在生成 coredump 文件后,退出程序,从而退出应用。此时只会生成一个 device 的 coredump 文件,丢失全局信息。
如果需要全局信息,可配置 export ALIPPU_MUTE_DEV_ERR=1, 该环境变量在发生 IH 后,会 hold 住现场,方便用于检查全局现场(此时可使用第四节的方案保存全局现场)。考虑部分框架像 Pytorch 在通信 kernel 执行超过一定时间仍不退出时会显示终止掉 kernel 执行,因此为了保持 PCCL kernel 异常现场,还需要额外设置环境变量 export NCCL_DISABLE_ABORT=1 。
此种 device 异常后保留现场不退出的做法与上述 3.2.1 节中介绍的保留 coredump 的方法是相冲突的,不要同时设置两种方法中提到的环境变量。另外它也不能保证所有的 device 异常现场都能成功保留。
4. hang 现场分析
1.4 release 后,pccl 通信库内部集成了状态监控与状态保存功能。状态监控用于辅助判断 hang 状态,状态保存功能支持在 hang 发生时,保存通信库和硬件内部状态,用于后续进一步定位 hang 的原因。
4.1 状态监控(timeout state monitor)
pccl 内部会记录每个 rank 每次通信操作 kernel launch 到 PPU 上后持续的时间,超过 5 分钟 (默认配置,可通过环境变量 PCCL_STATE_MONITOR_TIMEOUT_MS 配置,单位为毫秒)后无状态更新,会报 WARNING(配置 NCCL_DEBUG=INFO/WARN 后可见),并触发状态保存,所有状态保存文件都默认位于 $HOME/.pccl路径下。

状态保存包括 comm_dump、state_monitor_dump、proxy_dump 三个子目录,其中 proxy_dump 只在多机场景会产生。comm_dump 下每个文件对应一个 rank 在某一时刻产生的 dump 文件,文件内容包含当前的 workfifo 执行状态。state_monitor_dump 下每个文件对应一个 rank,文件内容包含该 rank 主动检测到 timeout 的日志。proxy_dump 与 comm_dump 类似,文件内容包含当前跨机收发状态。
更多可配置环境变量如下:
PCCL_DEBUG_DUMP_DIR=指定保存状态文件的目录。状态文件将保存在 /.pccl 目录下。默认保存在 $HOME/.pccl 目录下。
PCCL_STATE_MONITOR_LEVEL=[0,1,2]状态监控级别。0: 关闭状态监控;1: device 侧监控,能应对绝大部分 hang 场景且性能友好;2: host 侧监控,能应对所有 hang 场景但可能影响 latency。默认值为 1。
level 1 监控日志示例

level 2 监控日志示例

PCCL_STATE_MONITOR_DISABLE=[0,1]是否关闭状态监控。1: 关闭状态监控;0: 开启状态监控。配置 PCCL_STATE_MONITOR_DISABLE=1 或PCCL_STATE_MONITOR_LEVEL=0状态监控都会被关闭,前者在 1.4 rel 开始支持,后者 1.5 rel 开始支持,建议 1.5 rel 及之后的版本使用后者。
PCCL_STATE_MONITOR_DUMP_WHEN_EXCEPTION_DISABLE=1是否关闭自动状态保存。
0: 不关闭,检测到 timeout 后会打印 warning 并且保存 comm/proxy dump 状态文件;
1: 关闭,检测到 timeout 后只打印 warning 但是不保存任何状态文件。
PCCL_STATE_MONITOR_LOG_EVERY_MS=xx是否要显示实时的执行进度,以及每隔 xx 毫秒打印一次。xx=0: 不打印;xx>0: 每隔 xx 毫秒打印一次当前已入队和已结束的 op 数。
PCCL_STATE_MONITOR_DUMP_DIR_SIZE_LIMIT_MB= 指定 dump 目录最大空间限制,默认 2GB.
2.0 release 版本新增 RAS 功能支持,工具位于 PPU_SDK/pccl_tools/pcclras,支持在运行时由用户主动查询执行状态、触发 comm/proxy dump.
2.1 release 版本开始,PPU_SDK 不再包含通信库相关工具 pccl_tools,需要从独立发布的 pccl 包下找到 pcclras 工具,独立发布链接:https://art-pub.eng.t-head.cn/artifactory/generic-local/SAIL/v2.1.0/COMM ,发布包命名为pccl_2.1.0_<hggcrt_version>_<os_version>.tar.gz,请根据实际场景所需的系统版本和 hggc runtime 版本下载对应包。
使用方法:
查询状态:pcclras
触发 dump: pcclras -d 0x1

4.2 状态保存
目前支持保存 3 种不同的状态文件:
DUMP_ROUGH : 包含 communicator 中每个 channel 的 workFifo 与 peers(head/tail/step 等)信息,可直接打开。
DUMP_RAW : 导出 communicator 整个 binary 空间,包含更多数据,二进制文件,需要特定解析程序打开。
DUMP_HWINFO : core dump 文件,需要使用 ppu-gdb 解析。
通过配置 PCCL_COMM_DUMP_LEVEL 可以配置保存哪些文件,默认为 DUMP_ROUGH。例如:export PCCL_COMM_DUMP_LEVEL=DUMP_ROUGH,DUMP_RAW可同时保存 ROUGH 和 RAW 文件。
多机时还会额外 dump proxy 的状态文件,位于 $HOME/.pccl/proxy_dump 路径下。
所有状态文件默认位于用户 $HOME/.pccl/comm_dump 路径下,如:

触发状态保存有以下 2 种方法:
4.2.1 默认保存
如果状态监控发现有可疑 timeout 发生,会自动(无需用户参与)触发一次状态保存。
4.2.2 使用 pipe 文件触发
通过向 pipe 文件写入需要 dump 文件标识触发,例如:同时 dump ROUGH & RAW & HWINFO
echo -n DUMP_ROUGH,DUMP_RAW,DUMP_HWINFO > pipe_file_name
注:需要保存所有 rank 状态时,需要向所有 rank 的 pipe 文件均进行写入操作。
4.3 状态分析
目前上述状态文件收集后尚不能自动去解析并对问题类型做判断,尚需要转交给平头哥研发同学进一步做问题分析与定位。
5. 常用的 debug 环境变量配置说明
pccl 中常用的环境变量参考 nccl:
Environment Variables — NCCL 2.22.3 documentation
pccl 在 nccl 的基础上对部分环境变量做了改动。
NCCL_DEBUG
pccl 中新增了 VERBOSE 等级,可以显示更详细的信息。一般模型训练或推理任务建议至少设置 log 显示级别为 INFO。
NCCL_DEBUG_SUBSYS
新增了 DUMP用于区分现场保存过程中的日志。
注意:并非当下所有 NCCL 中具备的环境变量在 PCCL 上都支持,具体可支持的环境变量列表,可参考文档:PCCL: NCCL APIs及环境变量支持情况(v2.1)


