在昇腾设备上做分布式训练时,HCCL(Huawei Collective Communication Library)就是那个藏在底层、负责多卡和跨节点梯度同步的集合通信库。很多做模型训练的同学用过它,但真正参与过它开发的并不多。这篇东西我想从一个贡献者的视角,把从提 Issue 到 PR 合入的完整链路拆开讲一遍,包括什么样的 Issue 会被维护者认真看、PR 怎么写才不用来回折腾十轮、CI 挂了先查哪里、以及 code review 时那些不好意思问出口的潜规则。
如果你已经有 C/C++ 或 Python 基础,想找一个有真实落地场景的开源项目练手,HCCL 其实是个比想象中更友好的选择。这篇文章会从项目背景、Issue 规范、环境准备、PR 流程、CI 调试到合入后的收尾工作,逐步带你把整套流程走通。哪怕你还没碰过集合通信,只要愿意读代码、愿意跑测试,也能找到自己可以下手的位置。
1. 项目画像:先搞清楚 HCCL 到底是什么
1.1 它在分布式训练栈里的位置
在聊怎么给 HCCL 贡献代码之前,先花点时间把项目本身讲清楚。HCCL 是昇腾 AI 加速卡上的集合通信库,对标的是 GPU 生态里的 NCCL。训练大模型时,数据并行是最常见的并行策略,每张卡算完自己那一份梯度之后,需要把梯度同步到所有卡上,这个同步动作就是靠集合通信库来完成的。AllReduce、AllGather、ReduceScatter 这些通信原语,就是 HCCL 对外提供的核心能力。
你可以把它理解成快递系统里的分拣中心:每张卡都往里面投递自己的梯度包裹,分拣中心负责按照规则重新打包,再派送给所有卡。如果分拣中心效率低,整个训练任务都会卡在等待上。这也是为什么集合通信库的性能优化如此重要——哪怕只提升 10% 的通信效率,在大规模训练里节省的时间成本都是非常可观的。
对贡献者来说,这个位置意味着两件事:一是你写的代码会被真实的高性能计算场景使用,改动的影响面很直观;二是它涉及的知识面比较宽,包括操作系统、网络协议、硬件拓扑、并发编程,但每个方向都不是说你要成为专家才能参与,很多任务其实是在已有代码框架上做增量优化和修补。
1.2 代码仓库和模块划分
HCCL 的源码可以通过公开代码托管平台获取,常见的路径是在 Gitee 或 GitHub 上搜索相关组织下的 HCCL 仓库。拿到源码之后,你会发现它并不是一个特别庞大的项目,但目录结构划分得很清晰。核心内容一般集中在通信算子的实现、设备管理、拓扑发现、传输链路这几个模块里。
从新人的角度,我建议先不要把精力放在底层传输链路上,那个模块涉及到对硬件驱动的理解,排查问题的门槛很高。相对友好的切入点是集合通信算子的上层逻辑、工具脚本、文档注释和测试用例。比如你看到某个算子在特定数据大小下性能异常,顺着调用链往下查,可能定位到的是内存分配策略或者同步等待逻辑的问题,这种问题的修复往往只涉及几百行代码,但对于理解整个项目帮助极大。
顺便说一句,HCCL 的代码风格整体比较规整,大量使用 C++ 特性,但也保留了不少 C 风格的接口设计。原因很简单,这个库需要被上层框架(比如 PyTorch 的适配层)通过 C 接口调用,所以对外 API 用 C 接口更稳定,内部的实现则用 C++ 来保证开发效率。
1.3 贡献前的能力准备
先泼一盆冷水:给 HCCL 贡献代码,不是会写 Python 调几个框架就行的事情。它需要一定的 C/C++ 功底,至少要能读懂指针、引用、模板这些基础概念,理解多线程和锁的用法,以及具备通过日志和调试工具排查问题的经验。
但也不用被吓住,因为项目里不只是代码一种贡献形式。文档修正、示例代码、测试补充、Issue 复现验证,这些都是非常有价值的贡献方式。尤其对于第一次参与开源的人来说,从文档和测试入手,熟悉了整个流程之后再碰核心代码,是曲线比较平滑的一条路。
环境方面,如果你手头有昇腾设备,那当然是最好的,可以本地复现并验证性能改动。如果没有,也可以贡献一些不依赖硬件的代码逻辑优化,或者在 CI 环境里去跑测试。只不过需要提前说明的是,HCCL 的很多测试是依赖真实硬件环境的,纯软件模拟环境只能覆盖一部分功能,这个限制对所有贡献者都一样,不是你一个人的问题。
2. 从一条合格 Issue 开始
2.1 Issue 不是吐槽区
我见过很多新手在 GitHub/Gitee 上提 Issue,开头就是“训练报错了,求大佬看看”,然后附一张模糊的截图,没有版本号,没有日志,没有复现步骤。这种 Issue 基本不可能得到有效的回复——不是维护者不热情,而是信息不足以定位问题。高质量开源协作的第一步,是学会提一条合格的 Issue。
一个合格的 HCCL Issue,必须包含几个核心要素:问题现象、复现步骤、环境信息、日志信息。现象描述要准确,比如“在 8 卡环境执行 AllReduce 时,当数据量为 512MB 时性能比预期低 30%”就比“训练很慢”有用得多。复现步骤要可操作,别人按你的步骤能走通。环境信息包括操作系统版本、CANN 版本、HCCL 版本、固件驱动版本、卡型号和拓扑。日志信息则是运行时的报错输出、HCCL 日志(通常由环境变量控制开关)以及必要的堆栈信息。
有人可能会觉得,我提个 Issue 而已,还需要整理这么多东西吗?换个角度想,如果你是那个需要花半小时甚至更久去复现问题的维护者,你希望看到什么样的报告?将心比心,把信息整理清楚,本身就是对维护者劳动的尊重。
2.2 一份能加速处理的 Issue 长什么样
我以一个真实的 bug 类 Issue 为例,给你拆解一下模板要素:
标题:[Bug] AllReduce 在数据量为 256MB 时触发段错误 环境信息: - 操作系统:Ubuntu 20.04.6 LTS - CANN 版本:8.0.RC1 - HCCL 版本:v1.8.1 - 固件驱动:24.1.rc1 - 硬件:4 张 Atlas 训练卡,单机单卡环形互联 复现步骤: 1. 编译 examples/allreduce_benchmark,参数配置如下(省略具体参数) 2. 设置 HCCL_LOGFILE=/tmp/hccl.log 环境变量 3. 启动测试程序,数据量设置为 256MB 4. 观察程序退出码 期望行为:正常完成集合通信并输出正确结果。 实际行为:程序在通信初始化阶段崩溃,退出码 -11,堆栈显示在拓扑发现模块(具体报错粘贴)。 日志片段: (粘贴关键日志,避免贴整个文件)这个模板的信息密度很高,维护者拿到手可以直接开始复现。值得注意的一点是,“数据量为 256MB 时崩溃,128MB 或 512MB 时正常”这种信息非常关键,因为它能帮助维护者快速缩小问题范围——可能涉及内存池分配策略、通信缓冲区的边界条件,或者某个特定数据分片逻辑。
另外,如果问题涉及性能,最好附上基线数据和实测数据的对比,说明是在什么条件测的。性能问题比崩溃问题更难处理,因为它可能和网络拓扑、CPU 频率、PCIe/NVLink/HCCS 链路状态都有关,没有数据的性能 Issue 基本等于大海捞针。
2.3 Issue 里的沟通礼仪
Issue 提完之后,你可能会遇到几种情况。一种是维护者很快回复“能否提供更多信息”,这时你需要及时补充;一种是长时间没人回复,这并不一定代表你的问题不重要,可能是维护者比较忙,也可能是你的 Issue 确实缺少必要信息;还有一种情况是有人回复了,但是给了一个和你预期不一样的解释方向。
在 Issue 评论区沟通,要保持专业和耐心。不要用“这东西怎么这么难用”这种抱怨语气,直接陈述技术问题就好。如果某个对话已经偏离主题,可以礼貌地提醒对方回到问题本身。如果维护者要求你验证某个修复补丁,尽量第一时间去跑,然后把结果反馈到评论区——这是建立信任的过程。
这里还有一个很容易踩的坑:在 Issue 里贴完整的大文件日志。几万行的日志会把真正有用的错误信息淹没掉,正确做法是先用 grep 过滤掉无关内容,只保留报错前后的关键几十行,并在日志片段外简要标注每部分可能表示的含义。维护者每天要处理大量 Issue,信息越聚焦,你的问题被解决的优先级就越高。
3. 从 Issue 到开发计划
3.1 怎么筛选适合自己的任务
不是所有 Issue 都需要你写代码。HCCL 的项目维护者通常会给 Issue 打标签,比如 good first issue、help wanted、bug、enhancement 等。如果你是第一次参与,建议优先找 good first issue 或者文档增强类的任务,这类任务的技术依赖少,评审要求相对宽松,能帮你把整个工具链跑通。
筛选任务的时候,有几点经验可以分享。首先看 Issue 的创建时间——太老的问题可能已经没人关注,你做了也可能不被接受。其次是看评论区的活跃度,如果维护者在此前已经给过一些方向性建议,说明这个问题是被认可的,你可以在此基础上展开。第三是评估影响范围,尽量选那些改动文件不超过 10 个、核心逻辑相对独立的问题。
以 HCCL 为例,一个对新人比较友好的任务是“补充某个通信原语在异常输入下的错误码检查”,这种改动通常只需要在 API 入口增加参数校验,逻辑清晰、影响面可控。相比之下,“优化某拓扑下 AllReduce 的带宽利用率”这种任务虽然很有吸引力,但往往需要你深入理解硬件拓扑和网络通信机制,调试周期很长,不建议拿来做第一个 PR。
3.2 认领任务与沟通方式
找到合适的 Issue 之后,不要直接闷头开始写代码。正确的做法是先在这个 Issue 下面评论,说明你想认领这个任务,并简单描述你打算怎么解决。好处有三个:一是避免和其他贡献者撞车,让别人知道这个任务有人在做;二是维护者会给你反馈,如果方案有问题可以及时调整,避免白干;三是有沟通记录作为依据,后续你提交 PR 时维护者更容易建立上下文。
在评论认领任务时,可以简单描述你的技术背景和计划时间线,比如“我熟悉 C++ 和内存管理,计划两周内完成修复并提交 PR”。这种信息能打消维护者对新人执行力的顾虑。但要注意,一旦你承诺了时间线,最好能真的推进,如果有意外延期,也应该及时在 Issue 里同步,而不是一直沉默。
另外一个小技巧:认领任务后,可以先把相关代码读一遍,在评论里提出你的初判。比如“经排查,问题出现在 topology.c 中的设备发现逻辑,可能和 PCIe 链路宽度检测有关”。即使这个判断不完全正确,维护者也会觉得你是真的在做事,而不是随便占个坑。
3.3 本地开发环境搭建
开发环境搭建是很多新手真正卡住的地方。我的建议是分两步走:先搞定能在本地完成的工作(读代码、编译、跑静态检查),再解决需要硬件资源的工作(跑真实通信测试)。
HCCL 的代码构建一般依赖 Linux 环境、GCC 编译器、CMake 和 Python 工具链。拿到源码后,按 README 的说明安装好依赖,依次执行配置、编译、安装这几个步骤即可。在配置阶段有几个选项比较重要,比如是否启用测试代码、日志等级、调试符号等。如果你是做功能开发而非性能调优,建议打开调试符号和更详细的日志输出,方便定位问题。
没有昇腾硬件的情况下,依然可以完成编译验证,但链接阶段可能会缺少某些底层库。这种情况下,一个可行的替代方案是只编译与你改动相关的模块,做语法级别的验证,然后把完整的验证寄托在 CI 上。这个过程虽然不那么顺畅,但很多开源项目的贡献者都是这样工作的——本地环境不完全匹配,CI 反而成了最终裁判。
绑定硬件环境的测试跑不了,还有一个折中方案:编写针对纯软件逻辑的单元测试。比如某个函数负责解析环境变量、计算通信缓冲区大小或者维护内部状态,这种逻辑完全可以在宿主机上写单元测试跑起来。HCCL 中这一类可以脱离硬件验证的代码比你想象的多得多,这也是很多新人能够远程贡献的主要原因。
4. 写 PR:不只是把代码推上去
4.1 分支与提交规范
代码开发完成后,提交 PR 的第一步是在远端仓库创建自己的分支。分支命名建议遵循一定的规范,比如用 fix/ 开头表示 bug 修复,用 feature/ 表示新功能,用 docs/ 表示文档变更。这样维护者从分支名就能快速判断改动的性质。
分支创建好之后,开发过程中的 commit 信息也要讲究。我见过很多 PR 里一个 commit 写了 800 行改动,信息只是“fix bug”,这种提交历史基本没有可读性。更好的做法是遵循 Conventional Commits 规范,在提交信息里用简短的类型前缀说明改动类别,比如 feat: 新功能、fix: 修复问题、test: 测试相关、docs: 文档修改。同时,一个 commit 尽量只做一件事,把逻辑上独立的修改拆成多个 commit,方便 reviewer 逐个审查。
Git 操作层面有几个建议。一是经常拉取主分支的最新代码,及时 rebase 以减少合并冲突;二是在提交信息中用祈使句开头,比如 Fix double free in comm buffer,而不是 Fixing 或 Fixed;三是提交信息正文可以简单写清楚为什么做这个修改,以及实现的思路,但不要写废话。
4.2 代码风格与自检清单
在推上远端之前,先在自己的分支上做一轮自检,这种自检能大幅提高 PR 通过率。以 C++ 代码为例,重点检查以下几项。
第一,命名是否规范。HCCL 这类底层库对命名风格有严格要求,变量名要能清晰表达含义,避免 a、b、c 这种无意义命名,函数和类的命名要符合项目既有风格,不要一种模块用驼峰、一种用下划线,至少在同一个文件里保持一致。
第二,边界条件是否处理。比如你改了一个缓冲区分配逻辑,是否考虑了 size 为 0 的情况?是否考虑了内存对齐要求?是否能处理分配失败?这些边界条件往往是 bug 的温床。
第三,是内存和资源管理。C/C++ 项目最常见的问题就是内存泄漏、双重释放、资源未释放。如果你改动的代码涉及动态内存分配,仔细检查每条路径上资源是否都被正确释放。对于不熟悉 C++ 内存管理的同学,建议先读几遍项目里已有的分配释放逻辑,照葫芦画瓢比自由发挥更安全。
第四,日志是否恰当。HCCL 有自己的日志系统,在关键路径和错误分支上应该有合理的日志输出,方便线上问题排查。但日志也不能太多,每个正常操作都打一条日志会把性能拖垮。
第五,测试是否充分。如果改动修复了某个 bug,至少应该有一个能验证该 bug 被修复的测试用例。对于性能优化,则需要附上优化前后的基准测试结果。
4.3 PR 描述怎么写得让 Reviewer 秒懂
PR 描述是你和 reviewer 沟通的第一份材料,它的质量直接决定了 review 的顺畅程度。一份好的 PR 描述不需要长篇大论,但必须覆盖几个核心信息:这个 PR 解决什么问题、改动涉及哪些模块、实现思路是什么、测试结果如何、是否有关联的 Issue。
一个比较实用的模板结构如下:
## 背景 (2~3 句话说清楚为什么要做这个修改,关联的 Issue 编号) ## 改动内容 (列出主要改动文件和每个文件的核心变更点) ## 实现思路 (简要说明采用的技术方案,为什么选择这个方案而不是其他方案) ## 测试验证 (本地测试、单测、CI 结果、性能对比数据) ## 影响范围 (这个改动会影响哪些模块或场景,是否涉及接口变更、是否需要升级适配)写 PR 描述的时候,要站在 reviewer 的角度去写。reviewer 可能对你的改动上下文不熟悉,你要用最短的时间让他理解你在做什么、为什么这么做。不要直接拷贝 commit message 到 PR 描述里,commit message 是给代码历史看的,PR 描述是给人看的,两者内容可以有重叠,但 PR 描述应该更完整、更有逻辑。
还有一点:PR 描述里提到的测试结果一定要真实可查,不要编造数字。如果某个性能数据是在特定条件下测出来的,要如实写明测试环境和方法。reviewer 大概率会追着你问数据的来源,如果数据站不住脚,你的信誉会大打折扣。
5. 过 CI 和 Code Review 的硬仗
5.1 CI 跑哪些东西
提交 PR 之后,代码会自动进入 CI 流程。HCCL 的 CI 通常包括编译检查、单元测试、静态代码扫描、以及依赖于硬件环境的集成测试。你不一定能看到所有 CI 阶段,但编译检查和静态扫描基本每次都会触发。
CI 失败是每个贡献者都会遇到的事情,第一次不用慌。最常见的失败原因有三类:编译错误、代码格式不符合规范、测试用例挂了。编译错误比较直观,顺着日志里报错的文件和行号定位即可。格式问题则需要用项目指定的工具跑一遍自动格式化,比如 clang-format 或 astyle 之类,格式化完成后再提交。
测试用例失败的情况需要具体分析。如果在本地能复现,那就按正常的调试流程走;如果本地无法复现,则可能是环境差异导致的,此时可以在 PR 评论中说明情况,并请求维护者协助查看 CI 日志。有些 CI 失败是因为基础设施不稳定导致的偶发失败,比如网络超时、资源调度延迟,这种情况下重跑一次就过了,但如果是你的代码引起的,重跑多少次都是失败。
想减少 CI 往返次数,最好的办法是在本地尽量复现 CI 的检查项。比如提前在本地跑单元测试、静态检查、格式化校验,确保这些过了再推代码。CI 每失败一次,你的 PR 合入时间就延后一次,而每个维护者一天能处理的 PR 数量是有限的。
5.2 面对 review 意见的心态与技术准备
Code review 是整个贡献流程中压力最大但也最有价值的环节。你的 PR 提交后,维护者或社区成员会逐行查看代码,提出修改意见。这些意见可以是针对正确性的严重问题,也可以是对变量命名的吹毛求疵,甚至是对代码风格的偏执。
先说一个最重要的心态建设:review 意见不是针对你一个人的,它是针对代码本身的。看到“这里加个空指针检查”这种意见,不要兴奋,也不要失落,把它当作一次技术方案打磨的过程就好。
技术准备方面,你要能区分不同性质的 review 意见。如果是正确性问题,比如并发竞争、内存错误、逻辑漏洞,这个没有商量的余地,务必认真修改。如果是风格和可读性意见,虽然不强制,但建议尽量顺从,因为维护者比你更了解项目的历史惯性和后续维护成本。如果是方案层面的讨论,比如“你为什么会选择用自旋锁而不是互斥锁”,这种意见开放度比较高,你可以从实际场景和性能测试数据出发,据理力争,前提是你的论证有数据支撑。
有个经验可以分享:当你在 review 中修改代码之后,一定要在 PR 评论区回复每条意见的处理结果。常见的做法是直接用 GitHub/Gitee 的回复功能,加一段“已修复,见 commit xxxxxxx”或者“这个建议我不太认同,原因是……”。每个意见都有交代,reviewer 才能放心地在后续 commit 中只关注新增的改动。
5.3 反复修改与历史清理
除非你写代码真的行云流水,否则一个 PR 经过多轮 review 修改是非常普遍的事情。
每轮修改之后,你需要在 PR 里追加新的 commit。这里有一个困扰很多新手的问题:我改了一轮,产生了 3 个新 commit,历史能清理吗?
我的建议是分阶段处理。在你的 PR 还没有被 reviewer 大量关注之前,可以用 git rebase 把多个小 commit 合并成几个逻辑完整的 commit,让历史保持整洁。但当 reviewer 已经在旧 commit 上留过言之后,就不要再随意 rebase 了,因为那会让 review 评论和代码版本对不上,反而增加沟通成本。这个阶段你可以通过追加 commit 的方式表达,等 PR 合入时,平台一般会默认用 squash merge 的方式把整个 PR 压成一个 commit,这样最终历史依然干净。
Git 操作上还有一个注意项:rebase 时不要强推(git push --force)已经公开的 commit,如果你用了,一定要在 PR 评论里明确告知,否则别人本地的分支会变得非常混乱。更稳妥的做法是先 fetch 主分支最新代码,然后 rebase 到最新,再强推你的 PR 分支。
5.4 合入前最后一道关卡:签署与自评
很多开源项目在 PR 正式合入前还有一个轻量级的合规检查,常见的是贡献者许可协议(CLA)和开发者原创证书(DCO)。HCCL 这类商业驱动的开源项目通常都在意这种合规问题,因为它涉及代码的版权归属和法律风险。
如果合入前提示你需要签署 CLA,不要觉得麻烦,这是一条一次性流程,填一遍以后所有项目都能通用。DCO 的签署则更简单,一般只需要在你的 commit message 尾部追加一行 Signed-off-by: 你的名字 <邮箱>,表示你确认这些代码是你写的,或者你有权提交这些代码。很多新手一看到英文缩写就以为很复杂,其实整个流程五分钟内就能完成。
还有一个容易被忽略的步骤:合入前自己最后读一遍完整的 diff。尤其是改动后的文件,从 Git 的 diff 视角再审视一次。你会发现很多平时注意不到的小问题,比如误提交的调试代码、多余的空白改动、临时的日志输出。自己先把这些问题清理干净,再让维护者看到,能少挨很多批。
6. 合入之后与常见问题速查
6.1 合入不是终点
PR 合入之后,很多人会觉得这件事结束了,可以接着去做下一个任务。但从贡献者的角度,合入只是开始,真正验证你改动的时刻是在之后的一个月。
首先,你要关注合入后的 CI 情况。合入主分支并不意味着代码完全没问题,稳健的项目通常会在主分支上跑更长时间、更全面的回归测试。如果这些测试发现你引入了回归,维护者会在你的 PR 讨论里回复你,或者新建一个 Issue 指向你的提交。
其次,你可以继续保持对相关 Issue 的关注。如果你的改动修复了某个用户报告的 bug,可以留意用户侧有没有反馈“这个修复有效”或“问题仍然存在”的信息。如果问题仍然存在,你需要重新打开 Issue 继续排查,这也是开源社区协作的正常节奏。
另外,作为一个已经合入过代码的贡献者,你已经有资格去 review 别人的 PR 了。这是一个很好的学习机会——你会发现,坐在 reviewer 的位置上,你会更加理解那些你曾经觉得烦琐的规范,其实都是项目质量和可维护性的保证。
6.2 常见问题速查表
下面整理了一些 HCCL 贡献过程中常见的问题和排查方向,是我以及身边同事实际踩过的坑,供你参考。
| 问题现象 | 可能原因 | 排查思路 |
|---|---|---|
| 本地编译失败,报缺少头文件 | 依赖库路径未配置 | 检查 CANN 或驱动环境变量,确认 LD_LIBRARY_PATH 是否正确 |
| CI 失败,全部失败在编译阶段 | 拉取代码时未同步子模块 | 检查仓库是否用 --recurse-submodules 拉取,或手动更新子模块 |
| CI 失败,失败在静态扫描 | 代码格式不符合规范 | 本地运行 clang-format 等格式化工具后重新提交 |
| 本地单测通过,CI 单测失败 | 环境差异或测试数据不同 | 对比本地与 CI 的环境变量、依赖版本,必要时在 PR 中请求维护者获取 CI 日志 |
| 性能优化数据不佳 | 方案与硬件拓扑不匹配 | 尝试在不同卡数、不同数据量下进行基准测试,分析是否引入了不必要的同步 |
| 无法在本地复现 Issue 中的崩溃 | 缺少日志开关或特定环境变量 | 按 Issue 中提供的信息逐项核对,尤其是数据量、拓扑和驱动版本 |
| PR 长期无人 review | 维护者繁忙,或描述不清晰 | 在 PR 评论区礼貌 @ 维护者,或补充测试数据和复现步骤让问题更清晰 |
6.3 几条值得谨记的避坑心得
做了一段时间 HCCL 贡献之后,有几个踩过的坑让我印象很深,这里集中说一下。
第一,不要在 issue 里只问“怎么解决”而不提供任何上下文。一个好的问题,应该让人感觉你已经读过代码、有自己的猜测,只需要别人帮你确认方向。我在社区里看到过的最高效的一次提问,是一个贡献者直接贴出了他定位到的代码行号,并附上了他对问题的分析,维护者只回了一句“你的判断是对的,修吧”,这比来回追问五六轮高效太多。
第二,不要在一个 PR 里同时修多个不相关的问题。多个问题混在一起,reviewer 很难评估风险。一个 PR 解决一个问题,是开源协作的基本契约。如果你发现代码里另外有一个 bug,请新建一个 Issue 或者再开一个 PR,不要塞到当前这个里。
第三,不要忽视文档的力量。代码改动如果涉及对外行为的变化,比如环境变量语义变更、接口参数调整、日志输出变化,一定同步更新相关文档。你维护的不只是代码,还有这个项目的可理解性。很多 PR 因为文档没有同步更新而被要求返工,这种事情完全可以提前避免。
第四,不要在 rebase 的过程中引入重复的改动。很多新手在 rebase 主分支时因为冲突解决不当,把主分支的代码又复制了一份到自己分支里,导致 diff 里出现大量无关改动。遇到这种情况,建议用 git diff 对比主分支和自己分支的差异,检查是否只保留了你想要改动的文件。
最后再说一点,参与开源项目不是一个零和博弈。你可能提交的第一个 PR 会被拒绝,会被告知设计欠妥,甚至会被人说“这个思路根本不对”。这些都很正常,很多资深开发者当年的第一个 PR 也是被反复打回来的。关键是你能从反馈里学到东西,而不是被打击之后就放弃。
如果你手头有昇腾设备,又有兴趣深入了解分布式训练底层的通信逻辑,可以试着从跑通官方 benchmark 开始,然后自己设置一些异常数据或者异常环境变量,看看会发生什么。好奇心是最好的入口,而 Issue 和 PR 只是把你对问题的理解转化成最终代码的载体。只要你能把一件事写清楚、说清楚、改清楚,开源社区的大门对你就是敞开的。