Skip to content
Merged
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
3 changes: 3 additions & 0 deletions ops/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ grep -rl my_op . | xargs sed -i 's/my_op/<你的算子名>/g'
## 约定

- **目录名 = 算子名**(小写下划线,如 `gelu_and_mul`)
- **交付自查清单**: 见 templates/operator/README「交付自查清单」节
(2026-10-07 审计后新增——13 算子曾缺包化入口已补齐,后续算子
合并前照单自查,勿再欠账)
- **包化导入(多算子同进程必用)**: 目录含 `__init__.py`,
`from ops.sdpa import register_a1` / `from ops.embedding import
register_a1` / `from ops.sdpa_math import register_a1` 顶层名带包前缀,
Expand Down
29 changes: 29 additions & 0 deletions ops/_local_scalar_dense/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""ops._local_scalar_dense — aten::_local_scalar_dense 算子包。

包化约定(多算子同进程必用, 见 ops/README「包化导入」与
sdpa/reports/e2e_mini_llm.md 的同名冲突实证):
- 包态: from ops._local_scalar_dense import register_a1 ← 顶层名带包前缀
- 脚本态: sys.path.insert(0, 算子目录) 后 from register import ...
(单算子目录内运行不变)

wt 2026-10-07-fix 补包化入口(审计发现 13 算子缺失, #14 范式补齐)
# wt <wangt635@ustc.edu.cn>
"""
from __future__ import annotations

import importlib


def _pkg_import(name: str):
return importlib.import_module("ops._local_scalar_dense." + name)


def __getattr__(name: str):
if name == "register_a1":
return _pkg_import("register").register_a1
if name == "reference":
return _pkg_import("reference")._local_scalar_dense_reference
raise AttributeError(f"ops._local_scalar_dense has no attribute {name!r}")


__all__ = ["register_a1", "reference"]
29 changes: 29 additions & 0 deletions ops/clone/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""ops.clone — aten::clone 算子包。

包化约定(多算子同进程必用, 见 ops/README「包化导入」与
sdpa/reports/e2e_mini_llm.md 的同名冲突实证):
- 包态: from ops.clone import register_a1 ← 顶层名带包前缀
- 脚本态: sys.path.insert(0, 算子目录) 后 from register import ...
(单算子目录内运行不变)

wt 2026-10-07-fix 补包化入口(审计发现 13 算子缺失, #14 范式补齐)
# wt <wangt635@ustc.edu.cn>
"""
from __future__ import annotations

import importlib


def _pkg_import(name: str):
return importlib.import_module("ops.clone." + name)


def __getattr__(name: str):
if name == "register_a1":
return _pkg_import("register").register_a1
if name == "reference":
return _pkg_import("reference").clone_reference
raise AttributeError(f"ops.clone has no attribute {name!r}")


__all__ = ["register_a1", "reference"]
29 changes: 29 additions & 0 deletions ops/contiguous/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""ops.contiguous — aten::contiguous 算子包。

包化约定(多算子同进程必用, 见 ops/README「包化导入」与
sdpa/reports/e2e_mini_llm.md 的同名冲突实证):
- 包态: from ops.contiguous import register_a1 ← 顶层名带包前缀
- 脚本态: sys.path.insert(0, 算子目录) 后 from register import ...
(单算子目录内运行不变)

wt 2026-10-07-fix 补包化入口(审计发现 13 算子缺失, #14 范式补齐)
# wt <wangt635@ustc.edu.cn>
"""
from __future__ import annotations

import importlib


def _pkg_import(name: str):
return importlib.import_module("ops.contiguous." + name)


def __getattr__(name: str):
if name == "register_a1":
return _pkg_import("register").register_a1
if name == "reference":
return _pkg_import("reference").contiguous_reference
raise AttributeError(f"ops.contiguous has no attribute {name!r}")


__all__ = ["register_a1", "reference"]
29 changes: 29 additions & 0 deletions ops/copy_/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""ops.copy_ — aten::copy_ 算子包。

包化约定(多算子同进程必用, 见 ops/README「包化导入」与
sdpa/reports/e2e_mini_llm.md 的同名冲突实证):
- 包态: from ops.copy_ import register_a1 ← 顶层名带包前缀
- 脚本态: sys.path.insert(0, 算子目录) 后 from register import ...
(单算子目录内运行不变)

wt 2026-10-07-fix 补包化入口(审计发现 13 算子缺失, #14 范式补齐)
# wt <wangt635@ustc.edu.cn>
"""
from __future__ import annotations

import importlib


def _pkg_import(name: str):
return importlib.import_module("ops.copy_." + name)


def __getattr__(name: str):
if name == "register_a1":
return _pkg_import("register").register_a1
if name == "reference":
return _pkg_import("reference").copy_reference
raise AttributeError(f"ops.copy_ has no attribute {name!r}")


__all__ = ["register_a1", "reference"]
29 changes: 29 additions & 0 deletions ops/detach/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""ops.detach — aten::detach 算子包。

包化约定(多算子同进程必用, 见 ops/README「包化导入」与
sdpa/reports/e2e_mini_llm.md 的同名冲突实证):
- 包态: from ops.detach import register_a1 ← 顶层名带包前缀
- 脚本态: sys.path.insert(0, 算子目录) 后 from register import ...
(单算子目录内运行不变)

wt 2026-10-07-fix 补包化入口(审计发现 13 算子缺失, #14 范式补齐)
# wt <wangt635@ustc.edu.cn>
"""
from __future__ import annotations

import importlib


def _pkg_import(name: str):
return importlib.import_module("ops.detach." + name)


def __getattr__(name: str):
if name == "register_a1":
return _pkg_import("register").register_a1
if name == "reference":
return _pkg_import("reference").detach_reference
raise AttributeError(f"ops.detach has no attribute {name!r}")


__all__ = ["register_a1", "reference"]
29 changes: 29 additions & 0 deletions ops/detach_/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""ops.detach_ — aten::detach_ 算子包。

包化约定(多算子同进程必用, 见 ops/README「包化导入」与
sdpa/reports/e2e_mini_llm.md 的同名冲突实证):
- 包态: from ops.detach_ import register_a1 ← 顶层名带包前缀
- 脚本态: sys.path.insert(0, 算子目录) 后 from register import ...
(单算子目录内运行不变)

wt 2026-10-07-fix 补包化入口(审计发现 13 算子缺失, #14 范式补齐)
# wt <wangt635@ustc.edu.cn>
"""
from __future__ import annotations

import importlib


def _pkg_import(name: str):
return importlib.import_module("ops.detach_." + name)


def __getattr__(name: str):
if name == "register_a1":
return _pkg_import("register").register_a1
if name == "reference":
return _pkg_import("reference").detach__reference
raise AttributeError(f"ops.detach_ has no attribute {name!r}")


__all__ = ["register_a1", "reference"]
29 changes: 29 additions & 0 deletions ops/dropout/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""ops.dropout — aten::dropout 算子包。

包化约定(多算子同进程必用, 见 ops/README「包化导入」与
sdpa/reports/e2e_mini_llm.md 的同名冲突实证):
- 包态: from ops.dropout import register_a1 ← 顶层名带包前缀
- 脚本态: sys.path.insert(0, 算子目录) 后 from register import ...
(单算子目录内运行不变)

wt 2026-10-07-fix 补包化入口(审计发现 13 算子缺失, #14 范式补齐)
# wt <wangt635@ustc.edu.cn>
"""
from __future__ import annotations

import importlib


def _pkg_import(name: str):
return importlib.import_module("ops.dropout." + name)


def __getattr__(name: str):
if name == "register_a1":
return _pkg_import("register").register_a1
if name == "reference":
return _pkg_import("reference").dropout_reference
raise AttributeError(f"ops.dropout has no attribute {name!r}")


__all__ = ["register_a1", "reference"]
42 changes: 42 additions & 0 deletions ops/embedding/MERGE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# 多平台合并流程(MERGE)— embedding

> 新平台实现合入本目录的固定流程。范式实证:ascend910(PR#11)→
> cambricon(PR#9 rebase 合入)。核心原则:**黄金/测试/注册链复用,
> 只写 kernel 本体**。

## 七步流程

1. **黄金复用**:`goldendata/` 平台无关(CPU 生成),新平台直接跑
`script/check_accuracy.py`——不过黄金不谈合并
2. **kernel 本体**:`kernel/<platform>.py` 四件套——`embedding` /
`embedding_backward` / `PLATFORM` / `_DEVICE_PROBE`(注册守卫
能力探测)
3. **facade 注册**:`kernel/platform.py` 三处——`_BACKENDS` 设备
映射、`DISPATCH_KEYS`、`synchronize` 分支
4. **register 选择器**:`register.py` 的 `_BACKENDS` dict 加一行;
dispatch_key 冲突时(如 npu/mlu 同为 AutogradPrivateUse1)依赖
`platform=` 显式参数
5. **_profile 探测链**:`_profile.py` 加 try-import 段(顺序与 sdpa
对齐:mlu → xmlir → npu → cpu)
6. **三层验证**:`EMBEDDING_PROFILE=<platform>` 跑 kernel/op/framework
三层 + `example.py` 一键
7. **文档同步**:README/REPORT 平台列、reports/ 增量、本文件与
PLATFORM.md 绑定项、CHANGELOG

## 合并冲突解决范式(PR#9 rebase 实证)

- 文档冲突:双方内容**并列**(验证矩阵按平台列拆行),不删任何一方
- 代码冲突:统一采 **platform facade** 新范式(旧 `_load_backend` /
裸 `from kernel import` 全部迁移)
- rebase 后必须:本机全链回归 + `ops/test_packaging.py`(多算子
同进程)双绿才可合并

## 验证矩阵终态(三平台)

| 层 | 命令 | 结果 |
|---|---|---|
| kernel(ascend910) | `EMBEDDING_PROFILE=ascend910 python3 test/kernel_level.py` | 20 前向+6 反向 err=0.0 |
| op(ascend910) | `test/op_level.py` | 拦截 5 次·逐位·梯度 err=0.0 |
| kernel/op/应用(p800) | 同上 | 20/20+6/6 err=0;A1 拦截 5 次 |
| kernel/op/应用(cambricon) | `EMBEDDING_PROFILE=cambricon ...` | 见 reports/cambricon.md |
| 包化共存 | `python3 ops/test_packaging.py` | 16 算子导入+双注册+消费 全绿 |
50 changes: 50 additions & 0 deletions ops/embedding/PLATFORM.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# 平台绑定清单(Platform Binding)— embedding

> 当前交付包含三个平台:**ascend910**(厂商委托:index_select 同源
> err=0 + dense_backward 委托)、**p800-kunlunxin**(厂商委托同构,
> gatherFIX 探针见 reports/)与 **cambricon**(MLU590,Autograd key
> 注册——见 reports/cambricon.md §4)。
> 本文件记录不可凭直觉搬运的绑定结论;跨平台移植时逐项重验,不要把
> 单平台实验结果当成普适行为。

## 1. 可直接复用(平台无关)

| 内容 | 位置 |
|---|---|
| fp32 语义参考 | `reference.py` |
| 黄金规格与数据 | `goldendata/`(CPU 生成,天然跨平台) |
| 平台 facade(按张量设备路由) | `kernel/platform.py` |
| 三层测试、性能脚本 | `test/`、`script/`(`EMBEDDING_PROFILE` 切平台) |
| A1 autograd.Function 包装 | `register.py`(`_BACKENDS` 选择器 + `_DEVICE_PROBE` 守卫) |

## 2. ascend910 绑定(厂商委托)

| 绑定项 | 实测结论 |
|---|---|
| A1 拦截 key | **AutogradPrivateUse1**(PrivateUse1 永不命中——sdpa 开发报告 §3.1 dispatch 证据链同结论) |
| aten 签名坑 | `aten::embedding_dense_backward` **5 参无 sparse**(与 Python 层 6 参不同) |
| autograd.Function | staticmethod 读模块全局 → `register_a1` 里 `global` 全部三变量(PLATFORM/embedding/embedding_backward) |
| 同步 API | `torch.npu.synchronize`(非 cuda);`kernel/platform.py::synchronize` 已平台化 |
| 性能 | 委托=包装开销 0.62-0.99x native;Triton gather 探针 18-69x 慢(P800 结论在 Ascend 复现——embedding 是带宽型,自研 Triton 无优势) |

## 3. p800-kunlunxin 绑定

- XMLIR 将 XPU 呈现为 **CUDA 张量**(device.type=="cuda"),dispatch
key 为 AutogradCUDA
- gatherFIX 探针结论见 `reports/`(正确性 0 error;特化比 native 慢
10.9-177.9x——与 ascend910 的 Triton 探针结论一致)

## 4. cambricon(MLU590)绑定

- **Autograd key** 注册(与 configs/devices/cambricon.yaml 的
PrivateUse1 不同):embedding 带 autograd 的 A1 交付须注册 Autograd
key 才能携带自带 backward;两个 key 实测都能命中,取 Autograd key
以免覆盖 functorch 的 PrivateUse1 batch rule(reports/cambricon.md §4)
- 与 ascend910 同为 AutogradPrivateUse1 时:单机双 NPU+MLU 场景须
`EMBEDDING_PROFILE` 显式指定平台(`_backend_for` 的 platform 参数
优先于 dispatch_key 推断)

## 5. 新平台接入

按 `MERGE.md` 七步走;kernel 层实现 `embedding`/`embedding_backward`
+ `PLATFORM` + `_DEVICE_PROBE` 四件即可并入 `_BACKENDS`。
29 changes: 29 additions & 0 deletions ops/empty/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""ops.empty — aten::empty 算子包。

包化约定(多算子同进程必用, 见 ops/README「包化导入」与
sdpa/reports/e2e_mini_llm.md 的同名冲突实证):
- 包态: from ops.empty import register_a1 ← 顶层名带包前缀
- 脚本态: sys.path.insert(0, 算子目录) 后 from register import ...
(单算子目录内运行不变)

wt 2026-10-07-fix 补包化入口(审计发现 13 算子缺失, #14 范式补齐)
# wt <wangt635@ustc.edu.cn>
"""
from __future__ import annotations

import importlib


def _pkg_import(name: str):
return importlib.import_module("ops.empty." + name)


def __getattr__(name: str):
if name == "register_a1":
return _pkg_import("register").register_a1
if name == "reference":
return _pkg_import("reference").empty_reference
raise AttributeError(f"ops.empty has no attribute {name!r}")


__all__ = ["register_a1", "reference"]
29 changes: 29 additions & 0 deletions ops/empty_like/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""ops.empty_like — aten::empty_like 算子包。

包化约定(多算子同进程必用, 见 ops/README「包化导入」与
sdpa/reports/e2e_mini_llm.md 的同名冲突实证):
- 包态: from ops.empty_like import register_a1 ← 顶层名带包前缀
- 脚本态: sys.path.insert(0, 算子目录) 后 from register import ...
(单算子目录内运行不变)

wt 2026-10-07-fix 补包化入口(审计发现 13 算子缺失, #14 范式补齐)
# wt <wangt635@ustc.edu.cn>
"""
from __future__ import annotations

import importlib


def _pkg_import(name: str):
return importlib.import_module("ops.empty_like." + name)


def __getattr__(name: str):
if name == "register_a1":
return _pkg_import("register").register_a1
if name == "reference":
return _pkg_import("reference").empty_like_reference
raise AttributeError(f"ops.empty_like has no attribute {name!r}")


__all__ = ["register_a1", "reference"]
Loading
Loading