SuperAPI AI Directory

external-cannbot-ops-pypto-op-develop

Coding & development

View repository

Updated 10-15 17:19

About this skill

PyPTO Operator Implementation

Based on the requirements specification, design plan, and reference implementation, complete the code implementation, verification, and README delivery.


Required Inputs

Requirements Specification Information

From SPEC.md , extract:

Field Purpose
Operator name File naming, function naming
Mathematical formula Understand the computation logic
Input/output specifications (shape, dtype) Test data generation
Supported data types Test coverage, impl type handling
Precision requirements Test tolerance settings
Server type Environment compatibility confirmation

Design Plan Information

From DESIGN.md , extract:

Field Purpose
API mapping design {op}_impl.py Core implementation
Data specification design test_{op}.py Data generation + {op}_impl.py tensor description
Tiling strategy {op}_impl.py tiling configuration
Loop structure design {op}_impl.py kernel logic
Verification plan test_{op}.py test case design
Performance metrics README.md performance description

Reference Implementation Information

From {op}_golden.py , extract:

Information Purpose
golden function name {op}_golden() test_{op}.py import statement
Parameter signature test_{op}.py data preparation
Output format {op}_impl.py output tensor construction

If the above information is insufficient, ask the user questions step by step to supplement it.

Reference Files

File Purpose Loading Time
references/test-template.py Fixed template for test files Read when generating test_{op}.py
references/impl-template.py Fixed template for impl files Read when generating {op}_impl.py
references/execution-constraints.md PyPTO development execution constraints checklist Must-read before entering the implementation phase; refer to it repeatedly during coding and self-checks
references/error-code-troubleshooting.md Error code troubleshooting process and common error code quick reference Troubleshoot according to the process when verification fails
scripts/environment_prepare.sh Environment initialization script Execute as needed during the environment preparation phase
scripts/list_idle_chip_ids.sh Output the list of currently available chip ids (compatible with 910B / 910C) Set TILE_FWK_DEVICE_ID execute before

Development Phase

Phase One: Environment Preparation

  1. Check whether CANN is installed
echo ${PATH} | grep cann-8.5.0
  1. Check whether the pto-isa source code has been obtained
echo ${PTO_TILE_LIB_CODE_PATH}
  • If the path does not exist, execute scripts/environment_prepare.sh to perform environment initialization
  • If it is still unsuccessful, refer to docs/install/prepare_environment.md Get the pto-isa source code and set up environment variables
  1. Verify key documentation and example directories
ls docs/api/
ls examples/
  1. Set device_id
# 查找空闲 chip id
`bash scripts/list_idle_chip_ids.sh`

# 根据输出结果设置环境变量(例如输出为 "0 1 3 ..." 时,先选 chip 0)
export TILE_FWK_DEVICE_ID=$(bash scripts/list_idle_chip_ids.sh | awk '{print $1}')
export PTO_TILE_LIB_CODE_PATH=./pto_isa/pto-isa/
  • If the script produces no output, it means all current chips are occupied by processes and cannot be set arbitrarily TILE_FWK_DEVICE_ID

⚠️ Not setting TILE_FWK_DEVICE_ID will cause a runtime error: "If no NPU environment is available"

If the above checks do not pass, refer to the materials in docs/install to complete environment preparation.

Phase 2: Code generation

Output directory:custom/{op}/

Generation order:

  1. Based on the input information, first sort out the API mapping, tiling strategy, and loop structure, and proceed to implementation only after confirming feasibility
  2. Before entering implementation, read references/execution-constraints.md, and apply the framework-level constraints, basic type constraints, control flow constraints, and high-frequency operation constraints to this implementation
  3. Based on references/impl-template.py generate {op}_impl.py
  4. Based on references/test-template.py generate test_{op}.py(prerequisite:{op}_impl.py already generated)
  5. Generate README.md

⚠️ Implementation code and test code must be separated; mixing golden / impl / test into the same file is prohibited.


Generate {op}_impl.py

PyPTO kernel function implementation, generated based on the fixed template references/impl-template.py .

Before implementation, must check item by item references/execution-constraints.md, especially: output write-back, dynamic axis annotation, Element usage, TileShape, valid_shape, loop/cond, read-write loopback within the same graph.

Specification Description
Export function {op}_wrapper(x: torch.Tensor) -> torch.Tensor
Kernel decorator @pypto.frontend.jit
Tensor descriptor pypto.Tensor() or pypto.Tensor([pypto.DYNAMIC, ...], pypto.DT_FP32)
Tiling configuration Must call pypto.set_vec_tile_shapes(...) or pypto.set_cube_tile_shapes(...)
Output write-back output[:] = result or pypto.assemble(result, offset, output)
Optional helper function {op}_core() — split core computation logic for complex operators

Generate test_{op}.py

torch golden function precision comparison test, generated based on the fixed template references/test-template.py .

Structure:

Block Content
Import from {op}_golden import {op}_golden + from {op}_impl import {op}_wrapper
Environment tools get_device_id() — read TILE_FWK_DEVICE_ID
Test function test_{op}_levelN() — data generation → {op}_wrapper(x) → {op}_golden(x) → assert_allclose
CLI entry argparse, supports example_id / --list / --run_mode

Mandatory precision comparison specification:

Specification Description
Precision comparison Must use assert_allclose, see "Three state marker conventions"
Tolerance Simple operators rtol=1e-3, atol=1e-3; complex operators rtol=3e-3, atol=3e-3
NPU conditional comparison if run_mode == "npu": assert_allclose(...)
Manual comparison prohibited assert max_diff < tolerance / np.allclose() are all prohibited

Generate README.md

Must include:

  • Chinese description
  • Operator overview and formula
  • Directory structure
  • How to run
  • Verification entry
  • Known limitations

Mapping from Design to code files

design section test_{op}.py {op}_impl.py README.md
Overview Indirect reference No Yes
API mapping design No Yes Summarizable
Data specification design Yes Yes Summarizable
Tiling strategy No Yes Summarizable
Loop structure design No Yes Summarizable
Verification plan Yes No Yes
Performance metrics Partial Partial Yes
Deliverables list Yes Yes Yes

Stage 3: Test verification

Prefer using NPU mode for verification.

Verification steps:

  1. Compile and install(if pypto is not installed):
python3 build_ci.py -f python3 --disable_auto_execute

If already installed, there is no need to repeatedly compile.

  1. Run operator verification: When an NPU card is detected, directly use run_mode=npu to run:
python3 custom/{op}/test_{op}.py
  1. Verification failure handling: ⚠️ First confirm whether there is an error code: if yes, the error code process must be followed; if no, skip it Check method: search stderr or logs for Errcode: F / ErrCode: F
    • Has an error code (e.g. ErrCode: FC0000!) → the error code troubleshooting process must be followed: see references/error-code-troubleshooting.md
    • No error code → skip, and directly analyze the error message or logs to locate the problem

Recommended verification order:

  1. Small-scale functional verification: first confirm that the code can run and that the basic output shape is correct
  2. Typical-scale verification: use regular inputs from the target scenario for main-path verification
  3. Boundary and extreme value verification: check zero values, large values, special shapes, dynamic shapes, etc.
  4. Large-scale or performance-related verification: proceed only after functionality and precision are stable

Test type:

  • Unit test: basic functionality verification
  • Precision test: precision meets requirements
  • Performance test: performance measurement has been completed, and whether it meets requirements is judged based on measured data

⚠️ When an NPU card is available, do not use run_mode=sim。


Implementation notes

  1. A PyPTO tensor is uninitialized random values after creation: initialize before use, or ensure write-before-read; do not treat pypto.tensor(...) as an initialized tensor.
  2. Do not invent ops: during implementation, only use APIs already supported by PyPTO; when a missing capability is encountered, fall back to the API exploration or design stage for reconfirmation.
  3. Prefer using @pypto.frontend.jit style: choose the latest non-wrapper style, refer to docs/api/pypto-frontend-jit.md, and stay consistent with existing examples and documentation.
  4. golden / impl / test must have separated responsibilities: do not mix golden logic, implementation logic, and test logic in the same file.
  5. Use valid_shape for dynamic data ranges: when the last block's data amount may be smaller than the fixed block size,pypto.view / pypto.reshape must specify valid_shape。
  6. Use unroll_list for dynamic loop bounds: When the loop count is a dynamic value, you need to use unroll_list; When loops are nested in multiple levels, the innermost level uses unroll_list。
  7. matmul / cube scenario: Must confirm that set_cube_tile_shapes(...) is correctly configured.
  8. Output write-back must be done explicitly: Use output[:] = ...、output.move(...) or pypto.assemble(..., output); do not write output = ...。
  9. Dynamic axes must be explicitly annotated: All dynamic shape inputs and outputs must be marked as pypto.DYNAMIC / pypto.DYN。
  10. Element is used to fix scalar dtype: When a scalar participates in computation and the dtype cannot rely on implicit mapping, explicitly use pypto.Element(dtype, value)。
  11. Avoid read-write loops within the same graph: The same Tensor should not be both view read assemble and written back in the same graph.
  12. If the design already has tiling / loop constraints, prioritize following DESIGN.mdduring coding, and do not rewrite them on a whim.

Common Issues and Solutions

7 Common Types of Errors

  1. BFloat16 to NumPy conversion failure: Must first .float() and then .numpy()
  2. Environment variable not set: First run bash scripts/list_idle_chip_ids.sh to confirm an available chip id, then set export TILE_FWK_DEVICE_ID=<空闲 chip id>
  3. Dynamic axis defined in the wrong location: Must be defined outside the jit function
  4. Tile Shape not set: Before matmul, must call set_cube_tile_shapes; before vec operations, set_vec_tile_shapes
  5. Unreasonable precision standard: bfloat16 uses atol=0.0001, rtol=0.0078125
  6. Using PyTorch as Golden: When using NumPy to implement the golden function, bfloat16 data type conversion is not accurate enough; golden must independently be in {op}_golden.py, implemented using pure torch
  7. Error when SymbolicScalar is used as a list index:TypeError: list indices must be integers or slices, not SymbolicScalar. Reason:pypto.loop returns a compile-time symbolic value, not a Python runtime object. Solution: Use tensor slice or pypto.view/pypto.assemble to build the data flow.

Three Status Marker Conventions

Generated test_{op}.py must output the precision判定 marker using the following pattern:

import sys
import numpy as np

def run_test():
    # ... setup inputs, call golden and impl ...
    try:
        np.testing.assert_allclose(impl_output, golden_output, rtol=rtol, atol=atol)
        print("[PRECISION_PASS]")
    except AssertionError as e:
        print(f"[PRECISION_FAIL] {e}", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        # 功能问题(无标记),exit code ≠ 0
        print(f"Runtime error: {e}", file=sys.stderr)
        sys.exit(2)

if __name__ == "__main__":
    run_test()

Marker meanings:

  • [PRECISION_PASS]: Precision verification passed
  • [PRECISION_FAIL]: Precision verification failed (numeric mismatch)
  • No marker + exit ≠ 0: Functional issue (code crash, logic error, etc.)

assert_allclose thrown AssertionError contains Not equal to tolerance keyword, and the caller uses this to distinguish between "run failure" and "precision failure".


Checklist

  1. 3 files (test_{op}.py + {op}_impl.py + README.md) all exist
  2. test_{op}.py executable (no syntax errors)
  3. The test includes [PRECISION_PASS] / [PRECISION_FAIL] marker logic, with no other functional issues
  4. On verification failure, it has been confirmed whether there is an error code: if yes, follow the error code process; if no, skip
  5. {op}_impl.py has been self-checked according to references/execution-constraints.md : output write-back, dynamic axis, TileShape, valid_shape, Element, loop/cond, and assemble loop have all been checked