Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 152 additions & 0 deletions .github/skills/add-compat-api/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
---
name: add-compat-api
description: '循环新增 Paddle 对 PyTorch C++ 兼容接口。Use when: 有新增 PyTorch C++ API 需求时,在 Paddle compat 层新增接口与测试,并执行双仓编译、ctest、wheel 安装和回归验证。'
argument-hint: '传入 Paddle 仓库路径与 PyTorch 仓库路径(可选:PaddleCppAPITest 路径)'
---

# Add Compat API Loop

用于在 Paddle 兼容层中持续新增 PyTorch C++ API:
先补测试,再实现新接口,持续编译和回归,直到新增接口相关用例通过。

## 输入参数

- `PADDLE_ROOT`: Paddle 仓库路径,例如 `~/Paddle`
- `PYTORCH_ROOT`: PyTorch 仓库路径,例如 `~/pytorch`
- `PCAT_ROOT`: PaddleCppAPITest 路径,默认 `~/PaddleCppAPITest`
- `TORCH_DIR`: libtorch 路径,默认 `~/libtorch`

建议先设置:

```bash
PADDLE_ROOT=~/Paddle
PYTORCH_ROOT=~/pytorch
PCAT_ROOT=~/PaddleCppAPITest
TORCH_DIR=~/libtorch
```

## 适用场景

- 有新增 PyTorch C++ API 需要在 Paddle compat 层实现
- `bash test/result_cmp.sh ./build/` 仍出现 `FAILED/SKIPPED/DIFF`
- 需要新增 Device、Tensor、c10、ATen 等 compat 接口和测试

## 主流程(循环执行)

### Step 1. 确定本轮新增接口范围

1. 明确本轮要新增的接口(建议一次聚焦 1-3 个接口)
2. 在 `$PCAT_ROOT/test/` 中定位或补充对应测试(例如 Device 相关)
3. 明确接口行为基线:参数、返回、异常语义

### Step 3. 参考 PyTorch 实现并新增 Paddle compat 接口

1. 在 `$PYTORCH_ROOT` 中查找目标接口实现(声明 + 实现)
2. 在 `$PADDLE_ROOT/paddle/phi/api/include/compat` 中新增接口
3. 在 `$PADDLE_ROOT/test/cpp/compat` 中新增对应测试
4. 保持与 PyTorch 行为一致:
- 参数语义
- 返回类型与 dtype/shape
- 异常触发时机

### Step 4. 编译 Paddle 并跑兼容测试

```bash
cd "$PADDLE_ROOT/build"
ninja -j"$(nproc)"
ctest -R "ATen|c10|torch"
```

若此步失败,先修复 Paddle 侧编译或测试问题,再继续。

### Step 5. 安装新 wheel

```bash
pip install "$PADDLE_ROOT"/build/python/dist/*.whl --force-reinstall --no-deps
```

### Step 6. 回到 PaddleCppAPITest 复编并复测

```bash
cd "$PCAT_ROOT/build"
ninja -j"$(nproc)"

cd "$PCAT_ROOT"
bash test/result_cmp.sh ./build/
```

### Step 7. 判定是否继续循环

- 若新增接口相关用例仍有 `FAILED/SKIPPED/DIFF`:回到 Step 3,进入下一轮
- 若新增接口相关用例通过:进入收尾步骤

## 分支决策

### 分支 A:PaddleCppAPITest 编译失败(接口缺失)

- 优先补齐 compat 声明与最小实现
- 回到 Step 3 完善接口与测试后,再执行 Step 4-6 验证

### 分支 B:Paddle 编译通过但 `ctest` 失败

- 先修复回归,再安装 wheel
- 不要跳过 `ctest` 直接进入回归对比

### 分支 C:新增接口行为不一致

- 对照 PyTorch 检查 dtype 推导、边界输入、异常行为
- 仅处理本轮新增接口导致的问题,不处理历史遗留差异

### 分支 D:wheel 安装异常

- 确认 `build/python/dist/` 下有最新 whl
- 必要时先清理旧包后重装

## 完成标准

同时满足以下条件才算完成:

- `$PADDLE_ROOT/build` 下 `ninja -j"$(nproc)"` 成功
- `$PADDLE_ROOT/build` 下 `ctest -R "ATen|c10|torch"` 通过
- `$PCAT_ROOT` 下 `bash test/result_cmp.sh ./build/` 中新增接口相关用例通过
- 文档已更新:新增接口迭代记录(以及相关专题文档)

## 文档收尾要求

完成新增后,按以下固定模板更新文档(推荐记录到
`$PCAT_ROOT/doc/` 下的专题文档,必要时同步相关文档):

```markdown
## 对齐迭代记录(YYYY-MM-DD)

### 1) 接口变更
- 接口名:
- 变更类型:新增
- Paddle 兼容层位置:
- 参考 PyTorch 位置:

### 2) 测试覆盖
- 测试文件:
- 新增/修改用例:
- 覆盖点:shape / dtype / 边界 / 异常

### 3) 新增接口验证结果
- 新增前状态(缺失):
- 新增后验证结果:
- 关键行为说明:

### 4) 构建与回归结果
- Paddle 编译:通过/失败
- ctest (ATen|c10|torch):通过/失败
- result_cmp:无差异/仍有差异

### 5) 未完成项与下一轮计划
- 未完成接口:
- 下一轮优先级:
```

## 推荐执行节奏

- 每轮只处理一组强相关接口,避免一次修改过大
- 每轮都完整执行“编译→测试→安装→回归”闭环
- 以新增接口相关用例通过作为验收基线
94 changes: 94 additions & 0 deletions .github/skills/add-compat-api/references/Step3-1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Step 3 参考:从声明追踪到 PyTorch 实现

本文用于补充 Step 3 的第 1 步:从声明追踪到 PyTorch 实现。

## 第1步:先在 libtorch 查声明,再定位真实实现

目标:先从 libtorch 头文件确认 API 入口,再追踪到 PyTorch 源码中的最终 C++ 实现。

### 1) 先在 libtorch 中定位声明

将目标接口名记为 `<api_name>`,先在 libtorch include 目录搜索:

```bash
rg -n "<api_name>\(" "$TORCH_DIR/include/ATen" "$TORCH_DIR/include/torch"
```

常见声明位置:
- `$TORCH_DIR/include/ATen/ops/*.h`
- `$TORCH_DIR/include/ATen/core/*.h`
- `$TORCH_DIR/include/torch/csrc/api/include/torch/*.h`

### 2) 判断“有实现”还是“仅声明/转发”

找到声明后,分两类:

- 情况 A:头文件里有明确函数体
- 可直接把该函数体作为语义参考起点。

- 情况 B:只有声明,或转发到 dispatcher
- 常见形态:`at::_ops::<op>::call(...)`、`redispatch(...)`。
- 这通常表示该接口由 torchgen 生成包装层,不在该头文件里放最终业务实现。

对情况 B,继续执行第 3-6 步。

### 3) 在 PyTorch YAML 中找 schema 与 dispatch

在 PyTorch 源码中搜索:

```bash
rg -n "<api_name>" "$PYTORCH_ROOT/aten/src/ATen/native/native_functions.yaml"
```

在命中的 YAML 条目中提取:
- 函数 schema(func)
- dispatch 表(CPU/CUDA/Composite/Meta 等)
- 各后端对应的 kernel 名称

说明:
- PyTorch 会使用 `$PYTORCH_ROOT/torchgen`(例如 `/home/may/pytorch/torchgen`)解析 YAML,生成 libtorch 头文件与包装层。
- 因此 libtorch 中很多接口只有声明或轻量转发,真实实现需要继续沿 dispatcher 追踪。

### 4) 沿 dispatcher 链路追踪到 kernel 符号

把调用路径映射为:

1. 头文件声明/包装
2. `at::_ops::<op>::call`(生成代码)
3. dispatcher 注册路由
4. YAML dispatch 指向的后端 kernel 符号

再用 kernel 符号搜索真实实现:

```bash
rg -n "<kernel_symbol>\(" "$PYTORCH_ROOT/aten/src/ATen/native"
```

### 5) 仍未命中时,检查生成注册文件

有些场景下,先看生成的注册文件更快:

```bash
rg -n "<api_name>|<kernel_symbol>" "$PYTORCH_ROOT/build/aten/src/ATen"
```

重点关注 `Register*.cpp` 和生成的 ops 相关文件。

### 6) 在实现 compat 前,先落一份追踪记录

正式改 Paddle compat 之前,至少记录以下映射:

- libtorch 声明文件位置
- 声明是直接实现还是 dispatcher 转发
- YAML 条目与 dispatch 键
- PyTorch 最终 kernel 文件与函数

只有映射清晰后,才进入 compat 接口实现阶段。

## 快速检查清单

- 已先从 libtorch 声明开始查找
- 已确认是否属于 torchgen 生成转发
- 已定位 native_functions.yaml 的 schema 与 dispatch
- 已定位最终 C++ kernel 实现
- 未臆造上游不存在的实现
70 changes: 70 additions & 0 deletions .github/skills/add-compat-api/references/Step3-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Step 3 参考:第2步实现路径选择

本文用于补充 Step 3 的第 2 步:根据接口类别选择实现路径,避免在不合适的层面重复造轮子。

## 第2步:按接口类型分流实现

### A. `ATen/ops` 相关实现

适用范围:`/home/may/Paddle/paddle/phi/api/include/compat/ATen/ops` 下的接口。

处理原则:
- 优先在 `paddle::experimental` 命名空间查找对应 op。
- 先复用已有 `paddle::experimental::<op>` 语义,再做 compat 层参数/返回适配。
- 不直接复制 PyTorch 的底层实现细节,优先复用 Paddle 现有算子能力。

建议检查项:
- 参数顺序和默认值是否对齐
- dtype/device/layout 等选项语义是否一致
- 返回值结构(单 Tensor / 多返回)是否一致
- 异常触发条件是否一致

可用检索示例:

```bash
rg -n "paddle::experimental::<op>|experimental::<op>" "$PADDLE_ROOT"
rg -n "<op>\(" "$PADDLE_ROOT/paddle/phi/api/include/compat/ATen/ops"
```

### B. `Device`、`ScalarType` 等基础设施实现

适用范围:`Device`、`DeviceType`、`ScalarType`、类型转换、基础工具类等。

处理原则:
- 参考 PyTorch 对应实现进行语义适配。
- **宏定义要完全对齐**(条件分支、平台宏、功能开关宏的行为需一致)。
- 类和函数不要求逐字逐结构对齐,可按 Paddle 架构做适配封装。

关键约束:
- 宏语义一致性优先于类结构一致性。
- 可以调整内部实现方式,但外部可观察语义必须与 PyTorch 对齐。

建议检查项:
- `#if/#ifdef` 分支条件是否与 PyTorch 同语义
- 不同后端(CPU/CUDA/XPU/HIP)下行为是否一致
- 标量类型映射和边界值处理是否一致

### C. `Storage`、`DataPtr` 等底层张量基础实现

适用范围:`Storage`、`DataPtr`、intrusive_ptr、底层内存持有/释放相关逻辑。

处理原则:
- 当前这部分已具备相对完备实现,默认不做直接重构。
- 如确需改动,必须进入**人工审核**流程。

人工审核前置条件:
- 明确变更动机与风险(生命周期、所有权、别名、线程安全)
- 给出与 PyTorch 行为差异的可复现实验
- 提供最小修改方案与回滚方案

人工审核检查项:
- 所有权与释放路径是否安全(含 deleter)
- 拷贝/移动/共享语义是否被破坏
- device index、place、stream 语义是否回归
- 是否影响现有兼容测试稳定性

## 决策总结

- `ATen/ops`:先找 `paddle::experimental` 复用算子能力。
- 基础设施(`Device`/`ScalarType`):按 PyTorch 语义适配,宏定义完全对齐。
- 底层张量(`Storage`/`DataPtr`):默认不动,必须人工审核后再改。
Loading