# InfiniCore 开发者手册 Dear 开发者,感谢你参与 InfiniCore 开源项目的开发!本文档将帮助你了解如何向 InfiniCore 项目贡献代码。 ## 项目介绍 ### 项目模块体系 - infinicore:统一计算框架。提供 Python 和 C++ 接口,支持多种硬件平台。 - infinirt:统一底层运行时库,提供 C 语言接口,依赖 infini-utils。 - infiniop:统一底层算子库,提供 C 语言接口,依赖 infinirt。除了 C++ 算子实现之外,也包括使用九齿(triton)的算子实现,这部分算子需要在编译之前使用脚本生成源文件。安装后可以运行位于 `test/infiniop` 中的单测脚本进行测试。 - infiniccl:统一通信库,提供 C 语言接口,依赖 infinirt。 - infini-utils:全模块通用工具代码。 - utils-test:工具库测试代码,依赖 infini-utils。 - infiniccl-test:通信库测试代码,使用前需要安装好 infiniccl。 ### 文件目录结构 ```bash ├── xmake.lua # 总体 xmake 编译配置,包含所有平台的编译选项和宏定义 ├── xmake/*.lua # 各平台 xmake 编译配置, 包含各平台特有的编译方式 │ ├── include/ # 对外暴露的头文件目录,安装时会被复制到安装目录 │ ├── infinicore/*.hpp # InfiniCore计算库头文件(C++) │ ├── infiniop/*.h # InfiniOP算子库子头文件(C) │ ├── *.h/.hpp # 模块核心头文件 │ ├── src/ # 各模块源代码目录,包含源代码文件以及不对外暴露的头文件 │ ├── infinicore/ # InfiniCore源代码目录 │ │ ├── context/ # 张量运行时/硬件上下文管理源代码目录 │ │ ├── nn/ # 机器学习模块源代码目录 │ │ ├── ops/ # 张量算子源代码目录 │ │ ├── pybind/ # pybind 接口源代码目录 │ │ ├── tensor/ # 张量库源代码目录 │ │ │ ├── infiniop/ # InfiniOP算子库源代码目录 │ │ ├── devices/ # 每个设备平台各自的通用代码目录 │ │ ├── ops/ # 算子实现代码目录 │ │ │ ├── [op]/ │ │ │ │ ├── [device]/ # 各硬件平台算子实现代码目录 │ │ │ │ ├── operator.cc # 算子C语言接口实现 │ │ ├── reduce/ # 规约类算子通用代码目录 │ │ ├── elementwise/ # 逐元素类算子通用代码目录 │ │ ├── *.h # 核心结构体定义 │ │ │ ├── infinirt/ # InfiniRT运行时库源代码目录 │ ├── infiniccl/ # InfiniCCL集合通信库源代码目录 │ ├── test/ # 测试源代码目录 │ ├── infinicore/ # InfiniCore测试目录 │ │ ├── ops/*.py # 算子单测脚本(依赖各平台PyTorch) │ ├── infiniop/ # InfiniOP算子库单元测试目录 │ │ ├── *.py # 单测脚本(依赖各平台PyTorch) │ ├── scripts/ # 脚本目录 │ ├── install.py # 安装编译脚本 │ ├── python_test.py # 运行所有单测脚本 ``` ## 开发引导 ### 代码提交流程 1. 在github仓库issue页面根据任务类型(开发或bug)创建 issue,所有commit必须有对应的 issue 编号。 2. 外部人员需要通过 fork 代码仓库提交 PR。 3. 根据 issue 编号建立分支,分支名字格式为 `issue/#` (# 为issue 编号)。如果出现重复,可在后面添加“-#”序号,或用“/”后增加说明。 4. 所有 commit 信息必须以 `issue/#` 开头, 5. 分支推到远程后,建 Pull Request,标题需要以 `issue/#` 开头。在原issue页面上将该PR关联。 6. PR必须添加至少两位审核员(模块负责人和项目管理员等),PR中需附上最后一次修改后测试通过的截图。 7. PR通过审核,通过自动测试,无代码冲突后方可合并。合并后,关闭原 issue。 ### 如何开发一个新算子 - 如果你想通过 C++ 以及硬件原生语言开发一个新的算子,请阅读 [infinicore::ops 开发指南](/src/infinicore/ops/README.md) ### C++ 代码命名书写规范 1. 类型 内部数据结构类型 `UpperCamelCase` ```c++ // 尽量使用 Infinixx 开头 struct InfiniopMatmulCudaDescriptor; template class HashMap; using ValueMap = std::unordered_map; ``` 对外暴露的指针类型和枚举类型 `infinixx[XxxXxx]_t` 常量使用 `INFINI_UPPER_SNAKE_CASE` ```c++ typedef struct InfiniopMatmulCudaDescriptor *infiniopMatmulCudaDescriptor_t; typedef enum { // INFINI... INFINI_DTYPE_INVALID = 0, } infiniDtype_t; ``` 2. 普通变量、形参、类数据成员,使用 `snake_case` 成员名前下划线特指private成员,其他情况应避免使用前下划线 ```c++ int max_count; class Example { public: std::string getUserName(std::string user_id); private: // private数据成员名字前加下划线 int _max_count; std::string _user_name; }; struct UrlTableProperties { string name; int num_entries; static Pool* pool; }; ``` 当形参与函数内部变量或成员变量重名,可选择其中一个名字后加下划线。当函数内部临时变量和成员重名时,临时变量名字后加下划线。后下划线表示“临时” ```c++ void do(int count_){ int count = count_; } ``` 3. 函数,使用 lowerCamelCase ```c++ int getMaxValue() const; ``` InfiniCore 中和 torch 对齐的接口,使用 `snake_case`。 4. const/volatile修饰符写在类型前面 ```c++ const void *ptr; const int num; ``` ### 代码格式化 本项目分别使用 `clang-format-16` 和 `black` 对 C/C++ 以及 Python 代码进行格式化。可以使用 [`scripts/format.py`](/scripts/format.py) 脚本实现代码格式化检查和操作。 使用 ```shell python scripts/format.py -h ``` 查看脚本帮助信息: ```plaintext usage: format.py [-h] [--ref REF] [--path [PATH ...]] [--check] [--c C] [--py PY] options: -h, --help show this help message and exit --ref REF Git reference (commit hash) to compare against. --path [PATH ...] Files to format or check. --check Check files without modifying them. --c C C formatter (default: clang-format-16) --py PY Python formatter (default: black) ``` 参数中: - `ref` 和 `path` 控制格式化的文件范围 - 若 `ref` 和 `path` 都为空,格式化当前暂存(git added)的文件; - 否则 - 若 `ref` 非空,将比较指定 commit 和当前代码的差异,只格式化修改过的文件; - 若 `path` 非空,可传入多个路径(`--path p0 p1 p2`),只格式化指定路径及其子目录中的文件; - 若设置 `--check`,将检查代码是否需要修改格式,不修改文件内容; - 通过 `--c` 指定 c/c++ 格式化器,默认为 `clang-format-16`; - 通过 `--python` 指定 python 格式化器 `black`; ### vscode 开发配置 基本配置见 [xmake 官方文档](https://xmake.io/#/zh-cn/plugin/more_plugins?id=%e9%85%8d%e7%bd%ae-intellsence)。 - TL;DR - clangd 打开 *xmake.lua*,保存一次以触发编译命令生成,将在工作路径下自动生成 *.vscode/compile_commands.json* 文件。然后在这个文件夹下创建 *settings.json*,填入: > .vscode/settings.json ```json { "clangd.arguments": [ "--compile-commands-dir=.vscode" ], "xmake.additionalConfigArguments": [ // 在这里配置 XMAKE_CONFIG_FLAGS "--nv-gpu=y" ], } ```