跳到主要内容
TileLang 系统教程

tilelang-tutorial.huandu.me

第 20 章 IR 与编译期管线精读

/code/20-ir-and-pass-pipeline/

04-version-diff/compare_ascend_pipelines.py4195 字节
#!/usr/bin/env python3
"""Compare the Ascend pass vocabulary across the two locked repositories.

The book locks two Ascend sources:

    _vendor/tilelang-v0.1.15/            tilelang/ascend/pipeline.py   (in-tree)
    _vendor/tilelang-ascend-v0.1.2.000/  tilelang/engine/phase.py      (adapter)

They are *not* the same pipeline. This script extracts the pass names from both
and prints the difference, plus a targeted check for the ND->NZ pass name.

Usage:
    python3 compare_ascend_pipelines.py
    python3 compare_ascend_pipelines.py --grep InsertNd

Verification level: CPU logic verified (run on 2026-10-01, macOS, no GPU/NPU).
"""

from __future__ import annotations

import argparse
import re
from pathlib import Path

BOOK_ROOT = Path(__file__).resolve().parents[4]
MAIN = BOOK_ROOT / "_vendor" / "tilelang-v0.1.15" / "tilelang" / "ascend" / "pipeline.py"
ADAPTER = BOOK_ROOT / "_vendor" / "tilelang-ascend-v0.1.2.000" / "tilelang" / "engine" / "phase.py"
CORPUS_MAIN = (
    BOOK_ROOT.parent
    / "tilelang-corpus"
    / "02-tilelang-core-repo"
    / "raw"
    / "tilelang"
    / "tilelang"
    / "ascend"
    / "pipeline.py"
)

CALL_RE = re.compile(r"\b(?:tilelang|tir|ascend_transform|transform)\.([A-Z][A-Za-z0-9_]*)\s*\(")


def pass_names(path: Path) -> list[str]:
    text = path.read_text(encoding="utf-8")
    # Drop line comments so commented-out passes are not counted.
    text = "\n".join(line.split("#", 1)[0] for line in text.splitlines())
    names: list[str] = []
    for match in CALL_RE.finditer(text):
        name = match.group(1)
        if name in {"Target", "IRModule"}:
            continue
        if name not in names:
            names.append(name)
    return names


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--grep", default=None, help="substring to search in both trees")
    parser.add_argument("--compare-main", action="store_true",
                        help="also diff the in-tree pipeline against the corpus main snapshot")
    args = parser.parse_args()

    main_names = pass_names(MAIN)
    adapter_names = pass_names(ADAPTER)

    print(f"# in-tree Ascend pipeline: {MAIN.relative_to(BOOK_ROOT)}  ({len(main_names)} names)")
    print(f"# adapter pipeline:        {ADAPTER.relative_to(BOOK_ROOT)}  ({len(adapter_names)} names)")
    print()
    print("# only in the in-tree v0.1.15 Ascend pipeline")
    for name in main_names:
        if name not in adapter_names:
            print(f"  {name}")
    print()
    print("# only in the adapter v0.1.2.000 pipeline")
    for name in adapter_names:
        if name not in main_names:
            print(f"  {name}")

    if args.grep:
        print()
        print(f"# files under the two trees whose text contains {args.grep!r}")
        for root in (
            BOOK_ROOT / "_vendor" / "tilelang-v0.1.15",
            BOOK_ROOT / "_vendor" / "tilelang-ascend-v0.1.2.000",
        ):
            for path in sorted(root.rglob("*")):
                if not path.is_file() or path.suffix not in {".py", ".cc", ".h", ".md"}:
                    continue
                if any(part in {".git", "3rdparty"} for part in path.parts):
                    continue
                if args.grep in path.read_text(encoding="utf-8", errors="ignore"):
                    print(f"  {path.relative_to(BOOK_ROOT)}")

    if args.compare_main:
        print()
        if not CORPUS_MAIN.is_file():
            print(f"# corpus main snapshot not found: {CORPUS_MAIN}")
            return 0
        corpus_names = pass_names(CORPUS_MAIN)
        print(f"# corpus main snapshot pipeline: {CORPUS_MAIN}  ({len(corpus_names)} names)")
        only_main = [n for n in main_names if n not in corpus_names]
        only_corpus = [n for n in corpus_names if n not in main_names]
        print(f"# only in v0.1.15: {only_main if only_main else '(none)'}")
        print(f"# only in corpus main: {only_corpus if only_corpus else '(none)'}")
        print("# interpretation: an empty pair of diffs means every pass named above is")
        print("# already in the release, i.e. none of them is 'main-only'.")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

← 浏览本章全部代码