SuperAPI AI Directory

ascendc-operator-precision-eval

Data & analytics

View repository

Updated 10-15 19:58

About this skill

AscendC Operator Precision Evaluation

Skill Type: Evaluation type (test generation + execution + report output)

This skill performs systematic precision evaluation on a compiled and installed AscendC operator. The test cases consist of two parts: "conventional shape tests" and "boundary value tests". Each case iterates over all dtypes supported by the operator, and a structured precision report is output after running.

Prerequisites

  • The operator has been compiled and installed (theascend_kernel package can be imported or the .so file exists)
  • The operator has passed basic functional tests (tests/test_<op_name>.py exists and passes)
  • The operator name, PyTorch invocation method, input domain constraints, and all supported dtypes are known
  • csrc/ops/<op_name>/test/<op_name>-test-cases.md has been generated by ascendc-operator-testcase-gen (including SUPPORTED_DTYPES, TEST_SHAPES, BOUNDARY_VALUES, operator benchmark)

Core Flow

Phase 1: 加载用例文档 + 信息收集 → Phase 2: 用例适配 → Phase 3: 测试脚本生成 → Phase 4: 执行 → Phase 5: 报告生成

Phase 1: Load case document + information collection

Step 1.1: Load the testcase-gen case document (MANDATORY)

MUST First read csrc/ops/<op_name>/test/<op_name>-test-cases.md, and extract from it:

Extraction item Location in the case document Purpose
SUPPORTED_DTYPES §Test configuration dtype list iterated by precision testing
TEST_SHAPES §Test configuration shape list for conventional shape tests
BOUNDARY_VALUES §Test configuration scalar value list for boundary value tests
NPU invocation method §Operator benchmark NPU_CALL expression
CPU reference implementation §Operator benchmark CPU_REF expression

If <op_name>-test-cases.md does not exist: fall back to designing cases yourself (following the original Phase 2 flow), but the report must note that "the cases are self-designed, not produced by testcase-gen".

Step 1.2: Supplement information from the code

Supplement and extract the following information from the existing code:

Information Source Example
Operator name User input / op_host file name acosh
NPU invocation method register.cpp in m.def(cross-validated with the case document) torch.ops.npu.acosh(x)
CPU reference implementation PyTorch standard library (cross-validated with the case document) torch.acosh(x.cpu().float()).to(dtype)
Input domain constraints Mathematical definition / design.md x >= 1.0
All supported dtypes op_host TORCH_CHECK in (cross-validated with the case document) [torch.float16, torch.float32]
Supported dimension/shape constraints Logic in design.md / op_host elementwise supports arbitrary dimensions
Precision threshold Ecosystem operator open-source precision standard (see table below) Look up Threshold by dtype

Precision standard (ecosystem operator open-source precision standard)

Adopt MERE(mean relative error) and MARE(maximum relative error) are the two metrics for determination:

相对误差 = abs(actual - golden) / (abs(golden) + 1e-7)
MERE = mean(相对误差)
MARE = max(相对误差)

Introduce in the denominator 1e-7 to avoid division by zero when golden is zero.

Pass criteria:MERE < Threshold and MARE < 10 × Threshold。

dtype Threshold MERE upper limit MARE upper limit (10×)
float16 2⁻¹⁰ ≈ 9.77e-4 9.77e-4 9.77e-3
bfloat16 2⁻⁷ ≈ 7.81e-3 7.81e-3 7.81e-2
float32 2⁻¹³ ≈ 1.22e-4 1.22e-4 1.22e-3

For the complete dtype list (including HiFLOAT32, FLOAT8 E4M3/E5M2), see references/OPS_PRECISION_STANDARDS.md。


Phase 2: Test case adaptation

Prioritize reusing testcase-gen outputs: if Phase 1 successfully loaded <op_name>-test-cases.md, then TEST_SHAPES and BOUNDARY_VALUES are used directlyfrom the definitions in the test case document, with no need to redesign. Only design them yourself when the test case document does not exist.

Design principles

  1. Full dtype coverage: each shape / each boundary value traverses all dtypes supported by the operator
  2. shapes are determined by the operator: choose appropriate shapes based on the dimensions supported by the operator; do not write fixed dimensions
  3. shapes should not be too large: keep the number of elements per test case within a reasonable range to avoid unnecessary large tensors
  4. Total number of test cases = (len(TEST_SHAPES) + len(BOUNDARY_VALUES)) × len(SUPPORTED_DTYPES) ≥ 30

Part A: Regular shape tests (TEST_SHAPES)

Based on the dimensions supported by the operator, select suitable shapes from the following dimension pool to form the TEST_SHAPES list.

MUST Select based on the dimensions actually supported by the operator; do not select unsupported dimensions.

Shape selection reference pool

Dimension Recommended shape Applicable operator type
1D (128,), (1024,), (4096,), (8192,) elementwise, reduction
2D (32, 512), (64, 768), (128, 1024) elementwise, matmul, linear
3D (8, 16, 64), (4, 128, 256) elementwise, attention, conv1d
4D (4, 8, 32, 16), (2, 64, 32, 32) conv2d, elementwise
5D (2, 3, 4, 5, 6) conv3d, elementwise

shapes should not be too large: it is recommended that the number of elements in a single shape be ≤ 200K.

TEST_SHAPES format

TEST_SHAPES = [
    ("category_name", "description", (dim0, dim1, ...)),
    # ...
]

Category names can be customized; it is recommended to name them by dimension or scenario. Example:

# elementwise 算子(支持任意维度)
TEST_SHAPES = [
    ("1D",         "128 elements",         (128,)),
    ("1D",         "1024 elements",        (1024,)),
    ("1D",         "4096 elements",        (4096,)),
    ("1D",         "8192 elements",        (8192,)),
    ("2D",         "batch*hidden 32x512",  (32, 512)),
    ("2D",         "BERT-base 64x768",     (64, 768)),
    ("2D",         "BERT-large 128x1024",  (128, 1024)),
    ("3D",         "8x16x64",             (8, 16, 64)),
    ("3D",         "4x128x256",           (4, 128, 256)),
    ("4D",         "4x8x32x16",           (4, 8, 32, 16)),
    ("Production", "ViT 8x197x768",       (8, 197, 768)),
    ("Production", "single sample 1x512", (1, 512)),
]

Part B: Boundary value tests (BOUNDARY_VALUES)

For the operator's input domain, select key boundary points and typical values. Use the fixed small shape (1024,) for testing.

MUST Determine boundary values based on the operator's mathematical definition; different operators vary greatly.

Boundary value design guidance

Operator type Recommended boundary values
acosh (x≥1) x=1.0, x=1.001, x=10.0, x=1000.0
log (x>0) x=0.001, x=1.0, x=100.0, x=10000.0
sigmoid (full domain) x=0.0, x=-5.0, x=5.0, x=-20.0, x=20.0
sqrt (x≥0) x=0.0, x=0.001, x=1.0, x=10000.0
no domain restriction x=0.0, x=1.0, x=-1.0, x=100.0

BOUNDARY_VALUES format

BOUNDARY_VALUES = [
    ("description", scalar_value),
    # ...
]

Example (acosh):

BOUNDARY_VALUES = [
    ("domain lower bound x=1.0",  1.0),
    ("near boundary x=1.001",     1.001),
    ("moderate value x=10.0",     10.0),
    ("large value x=1000.0",      1000.0),
]

Phase 3: Test script generation

MUST first read the template files in the templates/ directory, replace the placeholders, and generate them into the test/ subdirectory of the operator directory.

Output directory

csrc/ops/<op_name>/test/
├── test_<op_name>_precision.py           ← pytest 测试
├── run_<op_name>_precision_report.py     ← 报告生成器
├── <op_name>_precision_report.json       ← JSON 报告(执行后生成)
└── <op_name>_precision_report.md         ← Markdown 报告(执行后生成)

Template files

Template Path Generation target
pytest test templates/test_op_precision_template.py csrc/ops/<op_name>/test/test_<op_name>_precision.py
Report generator templates/run_precision_report_template.py csrc/ops/<op_name>/test/run_<op_name>_precision_report.py

Placeholder replacement table

Placeholder Description Example (acosh)
{{OP_NAME}} Operator name acosh
{{NPU_CALL}} NPU call expression (using variable x) torch.ops.npu.acosh(x)
{{CPU_REF}} CPU reference baseline (using variable x, dtype) torch.acosh(x.cpu().float()).to(dtype)
{{SUPPORTED_DTYPES}} List of all supported dtypes [torch.float16, torch.float32]
{{INPUT_LOW}} Lower bound of the random input domain 1.0
{{INPUT_HIGH}} Upper bound of the random input domain 11.0
{{TEST_SHAPES}} Regular shape list (output of Phase 2 Part A) see the example above
{{BOUNDARY_VALUES}} Boundary value list (output of Phase 2 Part B) See example above

Precision metrics that must be collected

Decision metrics(used for pass/fail decision):

Metric Calculation method Pass condition
MERE ((npu - ref).abs() / (ref.abs() + 1e-7)).mean() < Threshold
MARE ((npu - ref).abs() / (ref.abs() + 1e-7)).max() < 10 × Threshold

Auxiliary metrics(used for analysis, not as decision basis):

Metric Calculation method Meaning
MaxAbsErr (npu - ref).abs().max() Maximum absolute error
MeanAbsErr (npu - ref).abs().mean() Mean absolute error
CosineSim F.cosine_similarity(npu.flatten(), ref.flatten()) Cosine similarity

Phase 4: Execute tests

4.1 Environment preparation

source /usr/local/Ascend/ascend-toolkit/set_env.sh
export PATH=/root/miniconda3/envs/py310/bin:$PATH

MUST Source the environment before each Shell invocation.

4.2 Run pytest

cd <project_root>
python3 -m pytest csrc/ops/<op_name>/test/test_<op_name>_precision.py -v --tb=short

4.3 Generate report

python3 csrc/ops/<op_name>/test/run_<op_name>_precision_report.py

4.4 Failure handling

Failure type Troubleshooting direction
RuntimeError (NPU kernel) Input data exceeds the domain / NPU does not support this dtype
AssertionError (precision) Check whether MERE/MARE slightly exceeds Threshold, analyze whether it is caused by boundary values
Individual dtype test cases FAIL Confirm whether the Threshold for this dtype matches, check whether MARE is concentrated at a few abnormal points
Many FAIL Check whether the operator Compute logic has bugs

4.5 In-depth troubleshooting of precision issues

When precision failures occur (allclose does not pass, output deviation is too large, output is all zeros/NaN) and cannot be resolved by simple threshold adjustments,MUST read and follow the ascendc-operator-precision-debug skill process for systematic root cause localization:

  1. Read ascendc-operator-precision-debug SKILL.md
  2. Execute according to its five-stage process: error analysis → code review → experiment isolation → instrumentation localization → fix verification
  3. After fixing, rerun the complete precision tests of this skill to confirm all pass

Note: only call when the precision issue cannot be resolved by adjusting thresholds. For cases where individual dtypes slightly exceed the threshold due to hardware precision characteristics, prioritize resolving by relaxing the threshold (and explain in the report).


Phase 5: Report generation

5.1 Markdown report

MUST Generate csrc/ops/<op_name>/test/<op_name>_precision_report.md, refer to templates/precision_report_template.md。

The report includes:

  1. Overview table: total test cases/passed/failed/pass rate
  2. Precision threshold standard table
  3. Regular Shape test results table(grouped by category)
  4. Boundary value test results table
  5. Summary statistics by dtype
  6. Key findings(≥3 conclusions)

5.2 Completion prompt (file + conversation)

  1. File:MUST Generate csrc/ops/<op_name>/test/<op_name>_precision_report.md(and in the same directory *_precision_report.json if the script outputs it), and provide the user with thecomplete path:
精度验证报告已生成:
  csrc/ops/<op_name>/test/<op_name>_precision_report.md
  csrc/ops/<op_name>/test/<op_name>_precision_report.json   # 若存在
  1. Current conversation:MUST also comply with the next section "Display results in conversation", and must not output only the path.

Display results in conversation (MANDATORY)

After pytest and the report script have finished executing and the Markdown/JSON have been generated, the assistant in thecurrent conversation's reply MUST:

  1. Paste readable conclusions(the user can grasp the results without opening files):
    • Overview: total test cases, passed count, failed count,pass rate(percentage).
    • If there are failures: list the failed test case identifiers (case name / shape / dtype / category), as well as the main error metrics (such as MaxAbsErr) or pytest summary lines.
    • If all pass: explicitly write "all passed" and the total number of test cases.
    • Key findings ≥ 3: may be consistent with the "Key Findings" in the report or distilled from the report (dtype differences, boundary value behavior, whether thresholds were tightened/relaxed, etc.).
    • Optional: a summary table of pass status by dtype (excerpt; when there are many cases, only summary rows may be listed).
  2. Criteria: explain in one or two sentences the precision standard used (MERE/MARE, ecosystem operator open-source precision standard) and the Threshold value for each dtype.
  3. Path last: after presenting the above content, then append <op_name>_precision_report.md(and the JSON) full path.

NEVER: reply only with "report generated" and the path; NEVER replace showing the pass rate and failure summary in the conversation with "please open the Markdown yourself".


Lessons Learned

Input Generation

  • Domain: be sure to consult the operator's mathematical definition to ensure the input is valid
  • fp16 range: fp16 maximum is about 65504, input must not exceed this value
  • shape size: it is recommended that the number of elements in a single shape ≤ 200K to avoid excessively long test time

Precision Metrics

  • MERE / MARE: decision metric, denominator is abs(golden) + 1e-7(not clamp), aligned with the ecosystem operator open-source precision standard
  • MaxAbsErr / MeanAbsErr: auxiliary analysis, helps determine the order of magnitude of the deviation
  • CosineSim: is 0 or NaN when the output is all zeros, needs to be annotated for explanation rather than judged as a failure

Threshold Explanation

  • Threshold source: ecosystem operator open-source precision standard (references/OPS_PRECISION_STANDARDS.md)
  • Pass condition: MERE < Threshold and MARE < 10 × Threshold
  • It is not recommended to relax the threshold arbitrarily; if relaxation is truly needed,MUST explain the reason in the report

Anti-patterns (NEVER)

  • NEVER only generate the report file without showing the overview and conclusions in the conversation
  • NEVER conceal the number of failed test cases and only report the path

Checklist

  • have read csrc/ops/<op_name>/test/<op_name>-test-cases.md(if it exists)
  • information collection complete (operator name, invocation method, input domain, all supported dtypes, supported dimensions)
  • TEST_SHAPES preferentially come from the testcase-gen case document, shapes are not too large
  • BOUNDARY_VALUES designed according to the operator input domain
  • total number of test cases = (shapes + boundary) × dtypes ≥ 30
  • every dtype supported by the operator has been tested
  • pytest all passed
  • JSON + Markdown reports have been generated
  • key findings ≥ 3
  • the user has been informed of the report and JSON paths (if generated)
  • shown in the current conversationoverview (pass rate), failure summary (if any), and ≥3 key findings, not just the path