跳转至主要内容
Version: v1.1.3

贡献指南

感谢每一位开发者对 Taichi 的贡献意愿。 Taichi 源自开源项目, 尽管我们一如既往地持续提升代码质量,但距离成为一个成熟的、大规模的工业级项目,Taichi 仍需努力。 这也是我们开源 Taichi 的初心:依靠社区力量,驱动 Taichi 发展壮大。 从文档更新、代码修复、功能开发等方面,只要发现相关的 GitHub issue ,非常欢迎和我们一起提 PR 做开发!

这篇文档将围绕开发者常遇到的处理 Github issue、参与测试、提交 PR 给到指南和提示,如果想成为 Taichi 贡献者,请仔细阅读本指南。 非常推荐大家在正式向 Taichi 做贡献之前,花些时间仔细阅读这篇文档。

通用指南与提示

这部分提供了一些同样对 Taichi 社区开发者的通用指南,以及一些非常有用的小技巧。

保持务实&不炫技

请提供直截了当的解决方案(有时甚至会“简单粗暴”):

  • "There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult." ——C.A.R. Hoare
  • "Perfection (in design) is achieved not when there is nothing more to add, but rather when there is nothing more to take away." ——Antoine de Saint-Exupéry

将优缺点并列

在做出设计决策之前,请充分考量优势与劣势。 只要一个设计中的优势远远高于劣势,那么这就是一个好的设计。

有效交流

我们的最终目标是希望能建立一个可持续、繁荣的 Taichi 社区,而有效交流则是通往这个目标的基石。 如下几点提示,能够促进有效交流:

  • 简洁:

    • 传递信息比堆砌词藻更重要 ,尽可能言简意赅。
    • 方便的话可引入图片、表格、列表等可视化内容。
  • 专业:

    • 将要发出的话再读两遍:所有观点都能通过这段话清晰表达吗?
    • 使用一些检查工具(如 Grammarly)在写作语法、风格、语气方面帮你更上一层楼。
  • 保持谦逊,有建设性:意见反馈与讨论请从基于事实,而不是从个人情绪出发:

    • 可接受的😊: “This design could be confusing to new Taichi users. If it were designed this way, it could...”
    • 不适宜的😞:“This design is terrible.”

可以贡献的内容

我们欢迎各种形式的贡献,包含并不局限于如下一些:

  • 修复一个 bug ;
  • 提出和开发新功能;
  • 改进或重构现存文档;
  • 对报错信息更友好提出建议;
  • 加入新的测试样例和示例 (demos) ;
  • 发布技术文章或教程;
  • 优化编译器性能;
  • 对文档、代码和注释的微调。

提交 issue

如果你建议新增一个功能,或是发现一个潜在的问题,你可以向 Taichi 项目提一个 issue。

note

When you try to report potential bugs in an issue, please consider running ti diagnose and offer its output as an attachment. 这将有助于我们更了解你的环境中,具体的代码上下文、系统信息,使调试过程更有效,更高效地解决你的问题。

caution

When filing your issue, review it once again to ensure that no sensitive information about your data or yourself creeps in.

认领一个 GitHub Issue

除了小的更新,大多数 PR 都是由开发者认领一个 issue 开始。本节提供一些相应的提示和最佳实践。 本节将提供相应提示和最佳实践。

如何找到适合第一次贡献的 GitHub Issues?

Issue 标签描述目标开发者群
good first issue比较容易上手开发的 Github IssueTaichi 初入门开发者
welcome contribution略有难度的 GitHub Issues希望深入开发 Taichi 的开发者

最佳实践

  • 当你决定认领一个 GitHub Issue 并进行开发:
    • 最佳实践:留言说明你将开发这个新的功能。
    • 目标: 避免不必要的重复工作。
    • 示例: 我知道如何修复这个 bug /开发这个新的功能,并愿意提供帮助。
  • 当你认领了一个 GitHub Issue 后:
    • 最佳实践:
      1. 简单描述你将如何进行开发(如果尚未明确具体的解决方式)。
      2. 直到核心开发者对你的行动计划回应后,再开始开发。
    • 目标: 保持修复好的性能简洁、高效。
    • 示例: GitHub Issue #2610

文档更新参考

作为增加社区口碑美誉度、提升开发者体验的一个重要途径,我们非常建议大家通过 PR 的方式来对文档进行更新。 在此展示关于文档更新的参考内容与小提示:

  • 文档源文件都被托管在 docs/ 文档站下。
  • 我们使用 GitHub Flavored Markdown (GFM) 和 Docusaurus 来建设文档站。 关于 Markdown 语法规则信息,请关注文档写作指南
  • 写作风格上,我们采用谷歌的文档风格, 具体指南点击这里
  • 建立本地 server 和重新浏览实时更新的文档,具体指南请参见 本地开发

为本地更改和添加测试样例

如果是开发新功能的 PR (pull request),非常建议你在提交前,你能够写出自己的测试样例,覆盖所有代码。

本地代码风格检验和测试整合

非常建议大家在提交 PR 之前,能够在本地完成代码样式检查和集中测试。

代码风格

Taichi 通过 预提交 commit 文件来执行代码风格,其中包括以下检查:

  1. C++ 代码由 clang-10 格式化。
  2. Python 代码基于 PEP 8 规则,由 yapf v0.31.0 格式化。
  3. Python 代码由 pylint 静态检查。

你需要事先安装 pre-commit:

pip install pre-commit

并运行代码检查器:

pre-commit run -a

使用此命令, yapf 将自动格式化您的 Python 代码。 您可以将其安装为预先提交的插件,以便在您将更改提交到git之前运行:

pre-commit install
如果没有在本地格式化代码风格,怎么办?

No problem, the CI bot will run the code checkers and format your codes automatically when you submit a PR.

关于 C++ 代码如何格式化的更多信息,请参考 我们的 C++ 风格

运行集成测试

运行所有的 C++ 或 Python 测试代码:python tests/run_tests.py

  • 例1: python tests/run_tests.py -v -t3 -a cpu,metal -s

    • -v: 详细输出。
    • -t <threads>: 自定义并行测试的线程数。
    • -a <arch(s)>: 只测试特定后端(用逗号分隔)。
    • -s: 测试原始输出。
  • 例2: python tests/run_tests.py numpy_io

    • <filename(s)>: 仅在指定的文件中运行测试案例(用逗号分隔)。
    • 这个命令所运行的测试都在 tests/python/test_numpy_io.py 文件中。
  • 例3: python tests/run_tests.py linalg -k "cross or diag"

    • -k <key>: 仅运行匹配指定键值的测试 (支持按键字符串中的表达式)。
    • 此命令运行 test_cross()test_diag()tests/python/test_linalg.py
  • 显示所有可用选项 python tests/run_tests.py -h

我们有 Python 和 C++ 测试案例,但默认情况下不建议用 C++ 测试案例。 要启用 C++ 测试案例:

  1. 从源代码构建 Taichi 需要使用 python setup.py develop 命令。
  2. 设置 TAICHI_CMAKE_ARGS="-DTI_BUILD_TESTS:BOOL=ON"

提交 Pull Request 请求 (PR)

现在终于来到了需要你提交辛苦开发出的 PR 们的时刻。 这部分将会介绍:

注意事项

  • 当实现复杂功能时:

    • 请考虑将它分成多个独立的、自成一体的PR,为社区同学提供更加明确的背景,保持更加可追踪的开发历史。
  • 当创建一个新的 PR 时:

    • 请确保你的 PR 仅有一个 issue:
      • 这样,你可以限定修改集合的范围内,保证这个修改能精准定位到具体问题。
      • 如果你在 PR 中包括不那么重要的改动,请确保它们是次要的。
      • 你的 PR reviewer 有权利要求你将 PR 中大规模、不那么重要的开发内容移除。
    • 如果您的 PR 要实现一个新功能,请确保你已经为它设置了测试样例。 查看 为您的本地更改添加测试样例
    • 您必须在本地为您的 PR 进行代码样式检查和集成测试。 查看 在本地进行样式检查和集成测试
  • 描述你的 PR:

    • 请你在 PR 描述中提供足够的信息,以便为社区同学提供更明确的背景:
      • 如果可以,请将 PR 链接到特定的 GitHub issue,例如 fixes #<issue_number>
      • 在描述中分享重要的设计决定。
  • 如果你创建了一个仍在进行的 PR:

    • 点击 Convert to draft ,将 PR 转换为草稿,表明你仍在开发进程中。
    • 点击 Ready for review 当你已经准备好推动 PR 进入 review 进程中。
    • 了解更多请关注 Draft

PR 的命名规范

你的 PR 将会出现在主分支的提交历史中,甚至是 Taichi 的 Release Note 中,因此,保证 PR 标题清晰易懂是很重要的。 本节介绍我们的 PR 命名规则:

[tag1] [tag2]...[tagN] 你的 PR 标题需要包含如下重要的信息 

^----^ ^----^...^----^ ^--------------------------------------------------^
| | | |
| | | +---> 请将标题首字母大写。
| | +---> 请将相邻标签精确地用一个空格分开。
| + --> 频繁使用的标签: [cuda], [lang], [ci], [ir], [refactor]
+---> 请在你的 PR 中至少包含一个标签。
  • PR 的命名规范:
    • 请在 PR 标题前加上至少一个标签,如 [lang]
    • 如果您有多个标签,请用一个空格分开相邻的标签。
    • 可用标签的完整列表请查看 misc/prtags.json
    • 通过 将标签首字母大写 的方式,我们来区分面向终端用户的 PR 和面向开发者的 PR。
      • 如果 PR 涉及到一个对终端用户可见的功能, 请初始化最相关的标签,这个 PR 也将进入到 Release Note 中。 例如, [Metal], [Vulkan], [IR], [Lang], [CUDA] 。 请保证你的 PR 名称中,至多只有一个上述格式的标签。
      • 如果一个PR涉及底层或中间实现,那么它是为开发者准备的,请确保它的所有标签格式都是 小写 的。 例如,[metal], [vulkan], [ir], [lang], or [cuda]
danger

错误写法 [Lang][refactor] (标签之间缺少空格)

tip

正确写法 [Lang] [refactor]

INCORRECT

[GUI] [Mac] Support modifier keys (both tags have their initial capitalized)

tip

正确写法 [gui] [Mac] Support modifier key (只有一个标签首次大写)

  • PR 的命名规范:
    • 请保持你的 PR 标题足够短,并确保已包含必要信息。
    • 请不要在 PR 标题中写入反引号 ("`")。
    • 将标题中紧接在标签(们)之后的第一个词初始字母大写。
danger

错误写法 [Doc] improve documentation (标签后的第一个单词首字母没有被大写)

tip

正确写法 [Doc] Improve documentation

note

以下是一些常用的标签:

  • [cuda]: 后端特定更改。
  • [lang]:前端语言功能,包括 syntax sugars;
  • [ir]: 中间代表权特定的变化。
  • [refactor]:代码重构。
  • [ci]: CI/CD 工作流程的更改。
  • [Doc]: 文档更新。

启用新标签时,请确保已将它其添加到 misc/prtags.json 中,以便其他人可以继续使用。

PR review & 合并清单

PR 审核或合并过程中,请遵循此清单:

  1. 请确保 PR 标题遵循我们的 命名规范

  2. 请确保 Taichi 的主分支有 线性历史。 查看 Linear vs Non-Linear History 了解更多信息。

  3. 请确保 PR 在合并前通过所有的持续集成(CI)测试。

    每次你 commit 到一个开着的 PR 时,CI 将被触发。 它在多个环境中构建并测试 PR 中的所有 commits。 请密切关注 CI 的测试结果。

    • A ✔️ 在 commit hash 的左侧:CI 已经通过;
    • A ❌ 在 commit hash 的左侧:CI 没有通过。

这里暂不赘述 Google 博客文章中所总结的最佳做法。 但是,如果你的 PR 正处于审核阶段,或者你正在审核别人的 PR,请抽出几分钟时间阅读它们。 强烈推荐!

C++ 代码风格规范

我们大体上遵循 Google C++ 代码风格规范。 一个主要的例外是函数命名惯例:不同于 Google 格式使用 驼峰命名法 命名函数,Taichi 采用蛇形命名法,例如 this_is_a_taichi_function()

这里强调一些被广泛使用的格式。

命名规范

  • 类和结构体名称应该使用驼峰命名法,例如: CodegenLlvm
    • 首选首字母缩略词(示例)。
  • 变量名称应该使用蛇形命名法,例如 llvm_context
  • 私有类成员变量名称应该以 _结尾,例如, id_to_snodes_
  • 常量名称应该使用驼峰命名法,前缀 k,例如: constexpr int kTaichiMaxArgs = 64;
  • 宏应该以 TI_为起点,例如 TI_NOT_implemented
    • 一般而言,尽量避免使用过多宏。
    • 在新代码中请避免使用 TI_NAMESPACE_BEGIN/END

经验法则:

  • 尽可能使用 const 。例如,函数参数类型、类成员函数等等。
  • 为类成员变量提供默认的初始化器,至少对 POD 类型是如此。
    class Foo {
    private:
    int x_{0};
    char* buf_{nullptr};
    };
  • 使用智能指针,避免 newdelete
  • 标记构造函数 explicit 以阻止编译器做任何隐式转换。
  • 避免在构造函数或析构函数中调用虚拟函数 (explanation)。

Deal with compilation warnings

Taichi implements warning-free code by turning on -Werror by default. This means that Taichi takes warnings as errors, and we highly recommend that you resolve a warning as soon as it occurs.

In the following section, we provide several practical tips for handling some of the common scenarios that you may encounter during CI compilation.

Deal with warnings that occur when compiling third-party header files

There is little we can do to third-party warnings other than turning them off. To turn off or mute warnings from specific third-party header files, use the SYSTEM option when configuring include_directories in your CMake files. Then, the included header files are treated as system headers. See the following two examples taken from cmake/TaichiCore.cmake:

# Treat files under "external/Vulkan-Headers/include" as system headers and mute warnings from them.
include_directories(SYSTEM external/Vulkan-Headers/include)

# Treat files under "external/VulkanMemoryAllocator/include" as system headers for target "${CORE_LIBRARY_NAME}"
target_include_directories(${CORE_LIBRARY_NAME} SYSTEM PRIVATE external/VulkanMemoryAllocator/include)

Deal with warnings when compiling third-party libraries or targets

Ideally, third-party libraries or targets ought to be built completely independent of your Taichi project. In practice, because of the design of the CMake system, CMake variables from the Taichi and third-party submodules are sometimes messed up. Therefore, we recommend that you disable warnings from a third-party library or target:

  1. Separate the submodule's CMAKE_CXX_FLAGS from the same variable defined in Taichi.
  2. Remove the -Wall option from the submodule's CMAKE_CXX_FLAGS variables.

Mute specific warning types across the entire Taichi project

You can find details about how to mute certain warning types from the Clang Compiler User Manual; it usually starts with -Wno-. 请解释警告是什么,以及我们为什么要在评论中忽略它。

下面的例子可以在 cmake/TaichiCore.cmake 中找到:

# [Global] Clang warns if a C++ pointer's nullability was not explicitly marked (__nonnull, nullable, ...).
# Nullability seems to be a clang-specific feature; thus we disable this warning.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-nullability-completeness ")

# [Global] By evaluating "constexpr", compiler throws a warning for functions known to be dead at compile time.
# However, some of these "constexpr" specifiers are debug flags and will be manually enabled upon debugging.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unneeded-internal-declaration ")

Mute warnings from specific code blocks

caution

The approach presented here is not recommended and considered your last approach, because it is not reliable.

In rare situations where you can neither fix nor mute the warnings from specific code blocks via conventional approaches, your last approach is to mute them by decorating your code block using the #pragma clang diagnostic macros. Beware that #pragmas are not defined in the C++ standard and that their implementations depend heavily on the compiler. 这就是说,这种解决办法既不稳定也不优雅。

To ignore all warnings from a specific code block, wrap it up with the following two groups of macros. Further, you can even replace -Wall with a group of warning types for finer control. 见以下示例:

#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wall"
#endif

{Your Code Goes Here}

#if defined(__clang__)
#pragma clang diagnostic pop
#endif

Handle special CI failures

Taichi's CI system is implemented using the Github Actions, the entrance of which lies in testing.yaml. Depending on the CI pipeline, testing.yml will execute one of the corresponding test scripts under this directory

There are a few CI pipelines that work slightly different from the standard CI pipeline:

CI pipeline - Build Android Demos

Build Andriod Demos builds both taichi-repo with your PR applied and an external taichi-aot-demo repo. After that, it executes the demos from taichi-aot-demo with the just-compiled Taichi program and libraries.

If your PR to taichi-repo contains changes to some public interface, you may need to adjust the codes in taichi-aot-demo to avoid breaking the demos. To achieve that, please follow these steps:

  1. File your PR to taichi-repo. If this PR changes the public interface, then it probably breaks the demos thus fail the Build Android Demos CI pipeline - Don't panic, this is expected.
  2. Update the demo codes in taichi-aot-demo to make it work with the above mentioned PR, then file a separate PR to taichi-aot-demo repo and have it merged.
  3. In the original PR to taichi-repo, update the commit id for taichi-aot-demo in aot-demo.sh. This time your PR is expected to pass Build Android Demos.

仍有问题?

如果遇到上述文档中未包含的问题,请直接在 GitHub Discussion 上提问或者在 taichi-dev/taichi 中开一个新的 issue 说明细节。 我们随时为你提供帮助!

最后,再次感谢每一位开发者愿意对 Taichi 贡献。 我们期待你的贡献成就!