Skip to content
Closed
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
107 changes: 99 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ on:
pull_request:

jobs:
# wt 2026-10-07-fix 新增 packaging 门: 算子包化回归(CPU 可跑部分)
# ——全算子 __init__.py 导入扫描; NPU 消费段在本机跑, CI 里跳过。
# # wt <wangt635@ustc.edu.cn>
ops-packaging:
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -70,9 +67,103 @@ jobs:
def anchors_of(p):
k = str(p)
if k not in anchor_cache:
text = p.read_text(encoding='utf-8', errors='replace')
hs = re.findall(r'^#{1,6}\s+(.*)$', text, re.M)
anchor_cache[k] = {
re.sub(r'[^\w\u4e00-\u9fff-]', '', h.strip().lower().replace(' ', '-'))
for h in hs}
try:
anchor_cache[k] = set(re.findall(r'<a id="([^"]+)"', p.read_text()))
except Exception:
anchor_cache[k] = set()
return anchor_cache[k]

for md in root.rglob('*.md'):
if '.git' in str(md):
continue
raw = md.read_text()
# mermaid 结构校验
for m in re.finditer(r'```mermaid\n(.*?)```', raw, re.S):
b = m.group(1)
if 'xychart' in b:
assert 'bar [' in b and 'x-axis' in b, f'{md}: xychart 缺件'
elif 'flowchart' in b:
pass # 网格/定位图可无边,只有流程图才要求边
# 链接检查(跳过代码块)
text = re.sub(r'```.*?```', '', raw, flags=re.S)
for m in re.finditer(r'\[([^\]]*)\]\(([^)#\s]+)(?:#([^)\s]+))?\)', text):
target, anchor = m.group(2), m.group(3)
if target.startswith(('http', 'mailto')):
continue
tp = (md.parent / target).resolve()
if not tp.exists():
errs.append(f'{md}: -> {target}')
elif anchor and anchor not in anchors_of(tp):
errs.append(f'{md}: #{anchor} in {target}')

print(f'检查完成: {len(errs)} 个错误')
for e in errs:
print(' -', e)
sys.exit(1 if errs else 0)
EOF

- name: Python 语法检查
run: |
python3 - <<'EOF'
import ast, pathlib, sys
fails = []
for p in pathlib.Path('.').rglob('*.py'):
if '.git' in str(p):
continue
try:
ast.parse(p.read_text(), filename=str(p))
except SyntaxError as e:
fails.append(f'{p}: {e}')
if fails:
for f in fails:
print(' -', f)
sys.exit(1)
print('Python 语法检查通过')
EOF

- name: YAML 配置检查
run: |
pip install pyyaml -q
python3 - <<'EOF'
import yaml, glob, sys
fails = []
for f in glob.glob('configs/devices/*.yaml') + glob.glob('inputs/*.yaml'):
try:
yaml.safe_load(open(f))
except Exception as e:
fails.append(f'{f}: {e}')
if fails:
for f in fails:
print(' -', f)
sys.exit(1)
print('YAML 检查通过')
EOF

- name: Intake manifest 契约校验
run: python3 scripts/intake_validate.py --validate-only

- name: 性能基线结构检查
run: |
python3 - <<'EOF'
import json, glob, sys
fails = []
for f in glob.glob('perf/baselines/*.json') + ['intake/manifest.schema.json']:
try:
d = json.load(open(f))
except Exception as e:
fails.append(f'{f}: {e}')
continue
if f.startswith('perf/'):
for k in ('schema', 'device', 'created_at', 'updated_at',
'git_commit', 'env_fingerprint', 'cases'):
if k not in d:
fails.append(f'{f}: 缺字段 {k}')
for cid, c in d.get('cases', {}).items():
if 'latency_ms' not in c.get('metrics', {}):
fails.append(f'{f}: {cid} 缺 metrics.latency_ms')
if fails:
for x in fails:
print(' -', x)
sys.exit(1)
print('性能基线结构检查通过')
EOF
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@

## [Unreleased]

### Changed
- **13 个 MLU 算子 register 签名对齐新库约定**(#19):
`_local_scalar_dense` / `clone` / `contiguous` / `copy_` / `detach` /
`detach_` / `dropout` / `empty` / `empty_like` / `empty_strided` /
`item` / `result_type` / `type_as` 统一支持
`counter` 拦截计数与显式 `platform` 参数;单平台 Cambricon 会校验
platform/dispatch key;aten 实现导入改为包态相对导入 + 单算子脚本
fallback,三个不可 A1 注册的算子保留原有禁用语义

### Fixed
- 恢复 #20 中被截断的 `docs-and-syntax` 完整脚本:Markdown 链接、
Python 语法、YAML、intake manifest 与性能基线结构检查重新生效;
保留新增 `ops-packaging` 门

### Added
- **sdpa_math 第二平台: p800-kunlunxin**(vendor O/LSE + exact-P + A1)
- `_profile` / benchmark / framework 消费方接入 P800;A1 使用
Expand Down
45 changes: 42 additions & 3 deletions ops/_local_scalar_dense/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,53 @@ def _bump():

def lsd_aten(self):
_bump()
from kernel.torch_level import _local_scalar_dense_torch
try:
from .kernel.torch_level import _local_scalar_dense_torch
except ImportError: # standalone single-operator script mode
from kernel.torch_level import _local_scalar_dense_torch
return _local_scalar_dense_torch(self)


def register_a1(dispatch_key="PrivateUse1"):
_PLATFORM_ALIASES = {"mlu": "cambricon", "mlu590": "cambricon"}
_SUPPORTED_PLATFORMS = {"cambricon"}
_SUPPORTED_DISPATCH_KEYS = {
"AutogradPrivateUse1", "PrivateUse1", "Autograd",
}


def _backend_for(dispatch_key: str, platform: str | None = None) -> str:
"""Resolve the sole current backend without silently accepting typos."""
requested = platform or "cambricon"
canonical = _PLATFORM_ALIASES.get(requested, requested)
if canonical not in _SUPPORTED_PLATFORMS:
raise RuntimeError(
f"未知 platform={platform!r}; 已支持: "
f"{sorted(_SUPPORTED_PLATFORMS)}")
if dispatch_key not in _SUPPORTED_DISPATCH_KEYS:
raise RuntimeError(
f"未知 dispatch_key={dispatch_key!r}; 已支持: "
f"{sorted(_SUPPORTED_DISPATCH_KEYS)}(或显式传 platform)")
return canonical


def register_a1(dispatch_key: str = "AutogradPrivateUse1",
counter: dict | None = None,
platform: str | None = None) -> torch.library.Library:
"""Register ``aten::_local_scalar_dense`` with optional interception counter.

``platform`` is accepted explicitly so a second backend can later use the
same call contract. These operators currently have one Cambricon backend.
"""
_backend_for(dispatch_key, platform)

def aten_impl(*args, **kwargs):
if counter is not None:
counter["n"] = counter.get("n", 0) + 1
return lsd_aten(*args, **kwargs)

global _LIB
_LIB = torch.library.Library("aten", "IMPL")
_LIB.impl("_local_scalar_dense", lsd_aten, dispatch_key)
_LIB.impl("_local_scalar_dense", aten_impl, dispatch_key)
return _LIB


Expand Down
45 changes: 42 additions & 3 deletions ops/clone/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,53 @@ def _bump() -> None:
def clone_aten(self, *, memory_format=None):
"""aten::clone(Tensor self, *, MemoryFormat? memory_format=None) -> Tensor"""
_bump()
from kernel.triton_level import clone_triton
try:
from .kernel.triton_level import clone_triton
except ImportError: # standalone single-operator script mode
from kernel.triton_level import clone_triton
return clone_triton(self, memory_format)


def register_a1(dispatch_key: str = "PrivateUse1") -> torch.library.Library:
_PLATFORM_ALIASES = {"mlu": "cambricon", "mlu590": "cambricon"}
_SUPPORTED_PLATFORMS = {"cambricon"}
_SUPPORTED_DISPATCH_KEYS = {
"AutogradPrivateUse1", "PrivateUse1", "Autograd",
}


def _backend_for(dispatch_key: str, platform: str | None = None) -> str:
"""Resolve the sole current backend without silently accepting typos."""
requested = platform or "cambricon"
canonical = _PLATFORM_ALIASES.get(requested, requested)
if canonical not in _SUPPORTED_PLATFORMS:
raise RuntimeError(
f"未知 platform={platform!r}; 已支持: "
f"{sorted(_SUPPORTED_PLATFORMS)}")
if dispatch_key not in _SUPPORTED_DISPATCH_KEYS:
raise RuntimeError(
f"未知 dispatch_key={dispatch_key!r}; 已支持: "
f"{sorted(_SUPPORTED_DISPATCH_KEYS)}(或显式传 platform)")
return canonical


def register_a1(dispatch_key: str = "AutogradPrivateUse1",
counter: dict | None = None,
platform: str | None = None) -> torch.library.Library:
"""Register ``aten::clone`` with optional interception counter.

``platform`` is accepted explicitly so a second backend can later use the
same call contract. These operators currently have one Cambricon backend.
"""
_backend_for(dispatch_key, platform)

def aten_impl(*args, **kwargs):
if counter is not None:
counter["n"] = counter.get("n", 0) + 1
return clone_aten(*args, **kwargs)

global _LIB
_LIB = torch.library.Library("aten", "IMPL")
_LIB.impl("clone", clone_aten, dispatch_key)
_LIB.impl("clone", aten_impl, dispatch_key)
return _LIB


Expand Down
45 changes: 42 additions & 3 deletions ops/contiguous/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,53 @@ def _bump() -> None:
def contiguous_aten(self, *, memory_format=torch.contiguous_format):
"""aten::contiguous(Tensor self, *, MemoryFormat memory_format=...)"""
_bump()
from kernel.triton_level import contiguous_triton
try:
from .kernel.triton_level import contiguous_triton
except ImportError: # standalone single-operator script mode
from kernel.triton_level import contiguous_triton
return contiguous_triton(self, memory_format)


def register_a1(dispatch_key: str = "PrivateUse1") -> torch.library.Library:
_PLATFORM_ALIASES = {"mlu": "cambricon", "mlu590": "cambricon"}
_SUPPORTED_PLATFORMS = {"cambricon"}
_SUPPORTED_DISPATCH_KEYS = {
"AutogradPrivateUse1", "PrivateUse1", "Autograd",
}


def _backend_for(dispatch_key: str, platform: str | None = None) -> str:
"""Resolve the sole current backend without silently accepting typos."""
requested = platform or "cambricon"
canonical = _PLATFORM_ALIASES.get(requested, requested)
if canonical not in _SUPPORTED_PLATFORMS:
raise RuntimeError(
f"未知 platform={platform!r}; 已支持: "
f"{sorted(_SUPPORTED_PLATFORMS)}")
if dispatch_key not in _SUPPORTED_DISPATCH_KEYS:
raise RuntimeError(
f"未知 dispatch_key={dispatch_key!r}; 已支持: "
f"{sorted(_SUPPORTED_DISPATCH_KEYS)}(或显式传 platform)")
return canonical


def register_a1(dispatch_key: str = "AutogradPrivateUse1",
counter: dict | None = None,
platform: str | None = None) -> torch.library.Library:
"""Register ``aten::contiguous`` with optional interception counter.

``platform`` is accepted explicitly so a second backend can later use the
same call contract. These operators currently have one Cambricon backend.
"""
_backend_for(dispatch_key, platform)

def aten_impl(*args, **kwargs):
if counter is not None:
counter["n"] = counter.get("n", 0) + 1
return contiguous_aten(*args, **kwargs)

global _LIB
_LIB = torch.library.Library("aten", "IMPL")
_LIB.impl("contiguous", contiguous_aten, dispatch_key)
_LIB.impl("contiguous", aten_impl, dispatch_key)
return _LIB


Expand Down
45 changes: 42 additions & 3 deletions ops/copy_/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,53 @@ def _bump() -> None:
def copy_aten(self, src, non_blocking: bool = False):
"""aten::copy_(Tensor self, Tensor src, bool non_blocking=False) -> Tensor"""
_bump()
from kernel.triton_level import copy_triton
try:
from .kernel.triton_level import copy_triton
except ImportError: # standalone single-operator script mode
from kernel.triton_level import copy_triton
return copy_triton(self, src, non_blocking)


def register_a1(dispatch_key: str = "PrivateUse1") -> torch.library.Library:
_PLATFORM_ALIASES = {"mlu": "cambricon", "mlu590": "cambricon"}
_SUPPORTED_PLATFORMS = {"cambricon"}
_SUPPORTED_DISPATCH_KEYS = {
"AutogradPrivateUse1", "PrivateUse1", "Autograd",
}


def _backend_for(dispatch_key: str, platform: str | None = None) -> str:
"""Resolve the sole current backend without silently accepting typos."""
requested = platform or "cambricon"
canonical = _PLATFORM_ALIASES.get(requested, requested)
if canonical not in _SUPPORTED_PLATFORMS:
raise RuntimeError(
f"未知 platform={platform!r}; 已支持: "
f"{sorted(_SUPPORTED_PLATFORMS)}")
if dispatch_key not in _SUPPORTED_DISPATCH_KEYS:
raise RuntimeError(
f"未知 dispatch_key={dispatch_key!r}; 已支持: "
f"{sorted(_SUPPORTED_DISPATCH_KEYS)}(或显式传 platform)")
return canonical


def register_a1(dispatch_key: str = "AutogradPrivateUse1",
counter: dict | None = None,
platform: str | None = None) -> torch.library.Library:
"""Register ``aten::copy_`` with optional interception counter.

``platform`` is accepted explicitly so a second backend can later use the
same call contract. These operators currently have one Cambricon backend.
"""
_backend_for(dispatch_key, platform)

def aten_impl(*args, **kwargs):
if counter is not None:
counter["n"] = counter.get("n", 0) + 1
return copy_aten(*args, **kwargs)

global _LIB
_LIB = torch.library.Library("aten", "IMPL")
_LIB.impl("copy_", copy_aten, dispatch_key)
_LIB.impl("copy_", aten_impl, dispatch_key)
return _LIB


Expand Down
Loading
Loading