NPU operator build & test framework
Project description
forge
NPU 算子编译测试框架。通过 JSON 配置文件驱动,统一管理不同代码仓的算子编译和测试流程,支持精度测试、性能测试和 git bisect 问题定位。
新增算子仓只需添加一个 JSON 配置文件,无需修改任何代码。
零第三方运行依赖,仅使用 Python 标准库。
安装
系统依赖
- Python >= 3.9
- Git(bisect 功能需要)
Python 依赖
运行时无需任何第三方库,仅使用 Python 标准库(argparse、json、csv、subprocess 等)。
开发依赖:pytest >= 7.0(仅运行测试需要)
安装步骤
方式一:venv 虚拟环境
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
方式二:conda 环境
# 在已有 conda 环境中安装
conda activate your_env
pip install -e ".[dev]"
# 或者新建专用环境
conda create -n forge python=3.9 -y
conda activate forge
pip install -e ".[dev]"
仅安装(不含 pytest):
pip install -e .
Web UI
使用浏览器界面(配置编辑、任务运行、bisect 可视化):
pip install 'ascend-forge[web]' # 方括号引号不要省,装上 web 额外依赖
forge web # http://127.0.0.1:8765
只用 CLI(不需要浏览器界面):
pip install ascend-forge # 不含 web 依赖
详见 forge_web/README.md。
架构
用户 CLI 命令
│
▼
cli.py ─── 解析参数,分派命令(argparse)
│
▼
config.py ─── 加载 JSON 配置,校验字段,替换占位符
│
├──▶ task.py ─── 通用任务执行引擎(TaskRunner 基类)
│ ├─ 单步/多步执行、skip 检查、capture 变量传递
│ ├─ 日志记录、超时控制、ignore_failure
│ └─ 子类通过 _post_step/_make_result 扩展
│
├──▶ builder.py ─── 编译任务(BuildRunner → TaskRunner)
│ ├─ _post_step: 产物检查(存在性、非空、时效性)
│ └─ 支持 checkout 到指定 commit 编译(自动 stash/恢复)
│
├──▶ tester.py ─── 测试任务(TestRunner → TaskRunner)
│ ├─ _post_step: 结果提取(stdout 正则 / CSV 文件)
│ └─ source_env 环境注入、repeat 重复聚合
│
├──▶ result.py ─── 结果持久化(~/.forge/results/)与对比
│
├──▶ workflow.py ─── 工作流引擎(WorkflowRunner)
│ └─ 按顺序执行命名任务序列,共享变量传递
│
└──▶ bisector.py ─── 二分查找问题 commit
└─ 循环:checkout → workflow → 判断 good/bad
项目结构
forge/
├── forge/
│ ├── cli.py # argparse CLI 入口
│ ├── config.py # 配置加载、校验、占位符替换
│ ├── executor.py # 通用子进程执行器(超时、输出捕获、实时流式输出)
│ ├── task.py # 通用任务执行引擎(TaskRunner 基类 + 共享工具函数)
│ ├── builder.py # 编译任务(BuildRunner 子类 + git checkout/restore)
│ ├── tester.py # 测试任务(TestRunner 子类 + 结果提取 + repeat 聚合)
│ ├── result.py # 结果持久化与对比
│ ├── workflow.py # 工作流引擎(WorkflowRunner:命名任务序列 + 变量传递)
│ ├── bisector.py # Git bisect 编排(使用 WorkflowRunner 执行每步)
│ ├── log.py # 日志系统(文件持久化 + 屏幕输出)
│ └── formatter.py # ASCII 表格格式化(bisect 结果输出)
├── configs/ # 算子仓配置文件(JSON)
├── tests/ # 测试用例(259 个,含端到端测试)
└── pyproject.toml
核心模块职责
| 模块 | 职责 |
|---|---|
config.py |
加载 JSON、校验必填字段、{placeholder} 替换、路径解析 |
executor.py |
subprocess 封装:超时控制、环境变量注入、输出捕获、实时流式输出 |
task.py |
通用任务执行引擎(TaskRunner 基类),封装单步/多步执行、skip、capture、日志等公共流程 |
builder.py |
BuildRunner 子类:产物检查(_post_step)+ git checkout/restore |
tester.py |
TestRunner 子类:结果提取(_post_step)+ source_env + repeat 聚合 |
result.py |
测试结果 JSON 持久化到 ~/.forge/results/,支持按 commit 加载和结果对比 |
workflow.py |
工作流引擎(WorkflowRunner),按顺序执行命名任务序列,步骤间通过 capture 共享变量 |
bisector.py |
在 good/bad commit 之间二分,使用 WorkflowRunner 执行每步的 workflow,支持 skip 和分支恢复 |
log.py |
日志文件持久化到 ~/.forge/logs/,控制屏幕输出级别 |
配置文件
每个算子仓对应一个 JSON 文件,放在 configs/ 目录下(或通过 --config-dir / FORGE_CONFIG_DIR 指定其他目录)。
真实仓配置推荐使用命名规范 repo-function-scenario.json,让文件名直接表达仓库归属、用途和默认场景,例如:
omni-accuracy-fuzz.jsonserver-deploy-mixed.jsontransformer-bisect-default.json
示例或演示配置可以保留通用前缀,但仍建议通过后缀表达主要用途和场景,例如 example-build-base.json、demo-env-source.json。
配置支持两种格式:
新格式(推荐)
使用 tasks + workflows + bisect.workflow 定义所有任务和执行流程:
{
"name": "my_repo",
"description": "Ascend 910 算子库",
"working_dir": "/home/user/repos/my_repo",
"env": {
"http_proxy": "http://proxy.example.com:8080"
},
"tasks": {
"build": {
"steps": [
{
"name": "compile",
"command": "bash build.sh",
"args": ["--ops={op_name}", "--target={target}"],
"working_dir": ".",
"env": { "ASCEND_HOME": "/usr/local/Ascend" },
"timeout": 600,
"success_pattern": "Build succeeded",
"artifacts": ["output/libkernel.so", "output/op_*.bin"]
},
{
"name": "install",
"command": "bash install.sh",
"working_dir": ".",
"timeout": 120,
"success_pattern": "Install succeeded"
}
]
},
"test_accuracy": {
"source_env": "{install_path}/set_env.sh",
"steps": [
{
"name": "generate input",
"command": "python gen_input.py",
"args": ["--op", "{op_name}"],
"working_dir": "tests/"
},
{
"name": "run operator",
"command": "bash run_op.sh",
"args": ["{op_name}"],
"working_dir": "."
},
{
"name": "compare result",
"command": "python compare.py",
"args": ["--op", "{op_name}"],
"working_dir": "tests/",
"success_pattern": "PASS",
"result": {
"type": "stdout",
"pattern": "accuracy: ([0-9.]+)"
}
}
],
"timeout": 300
},
"test_performance": {
"command": "bash run_perf.sh",
"args": ["--op", "{op_name}", "--iterations", "100"],
"working_dir": "tests/",
"timeout": 0,
"result": {
"type": "file",
"path": "output/perf_result.csv",
"format": "csv",
"value_column": 3,
"op_column": 0,
"header": true,
"delimiter": ",",
"aggregate": "avg"
}
}
},
"workflows": {
"accuracy_pipeline": {
"steps": ["build", "test_accuracy"]
},
"perf_pipeline": {
"steps": ["build", "test_performance"]
}
},
"bisect": {
"test_type": "accuracy",
"workflows": ["accuracy_pipeline"],
"regression": 15.0,
"threshold": null
}
}
旧格式(向后兼容)
使用 build + tests + bisect.build_before_test 的旧格式仍然可用,框架会自动转换并显示迁移提示:
{
"name": "my_repo",
"description": "Ascend 910 算子库",
"working_dir": "/home/user/repos/my_repo",
"env": {
"http_proxy": "http://proxy.example.com:8080"
},
"build": {
"command": "bash build.sh",
"args": ["--target=ascend910", "--build-type=Release"],
"working_dir": ".",
"env": {
"ASCEND_HOME": "/usr/local/Ascend"
},
"timeout": 600,
"success_pattern": "Build succeeded",
"artifacts": ["output/libkernel.so", "output/op_*.bin"]
},
"tests": {
"accuracy": {
"command": "python run_accuracy.py",
"args": ["--op", "{op_name}"],
"working_dir": "tests/",
"timeout": 300,
"success_pattern": "PASS",
"result": {
"type": "stdout",
"pattern": "accuracy: ([0-9.]+)"
}
},
"performance": {
"command": "bash run_perf.sh",
"args": ["--op", "{op_name}"],
"working_dir": "tests/",
"timeout": 0,
"result": {
"type": "file",
"path": "output/perf_result.csv",
"format": "csv",
"value_column": 3,
"op_column": 0,
"header": true,
"delimiter": ","
}
}
},
"bisect": {
"build_before_test": true,
"regression": 15.0,
"threshold": null
}
}
自动转换规则:
build配置 →tasks.buildtests.accuracy→tasks.test_accuracy,tests.performance→tasks.test_performance- 列表格式 workflow
["a", "b"]→ 对象格式{"steps": ["a", "b"]} bisect.build_before_test: true→ 自动生成_bisect_autoworkflow["build", "test_{type}"]
建议逐步迁移到新格式。
字段说明
顶层字段:
| 字段 | 必填 | 说明 |
|---|---|---|
name |
是 | 仓库唯一标识 |
description |
否 | 简短概述,适合 forge list 这类列表视图展示 |
usage |
否 | 详细使用说明,适合 forge show / forge usage 展示 |
working_dir |
是 | 工作目录路径(绝对路径,或相对于配置文件所在目录) |
vars |
否 | 自定义变量字典,可在所有占位符中使用。CLI --arg 可覆盖 |
env |
否 | 全局环境变量字典,所有任务继承。task/step 级别的 env 可覆盖 |
source_env |
否 | 环境变量脚本路径(绝对路径,支持 {placeholder})。任务执行前 source 该脚本注入环境变量 |
description 只负责提供一句话的短说明,供 forge list 快速浏览;usage 则用于承载更完整的使用指导、参数约定和示例命令。建议在 usage 中采用轻量级小节标题:使用场景:、使用方法:、示例:,方便 forge show 和 forge usage 直接输出。
tasks 字段:
| 字段 | 必填 | 说明 |
|---|---|---|
tasks.<name>.command |
是* | 任务命令(单步模式) |
tasks.<name>.args |
否 | 命令参数列表 |
tasks.<name>.working_dir |
否 | 工作目录,相对于 working_dir,默认 "." |
tasks.<name>.env |
否 | 额外环境变量(覆盖顶层 env) |
tasks.<name>.timeout |
否 | 超时秒数,默认 600。设为 0 或 null 不限时 |
tasks.<name>.source_env |
否 | 该任务专用的 source_env,覆盖上层配置 |
tasks.<name>.success_pattern |
否 | 正则匹配 stdout 判断成功,支持字符串或数组(AND)。不配置则仅依赖退出码 |
tasks.<name>.artifacts |
否 | 产物路径列表,支持 glob 通配符。检查文件存在、非空、且修改时间在执行之后 |
tasks.<name>.result.type |
否 | "stdout" 或 "file" |
tasks.<name>.result.pattern |
stdout 时必填 | 正则表达式,第一个捕获组为数值 |
tasks.<name>.result.path |
file 时必填 | CSV 文件路径,相对于 working_dir |
tasks.<name>.result.value_column |
file 时必填 | 数值所在列(从 0 开始) |
tasks.<name>.result.op_column |
否 | 算子名所在列 |
tasks.<name>.result.header |
否 | 是否有表头行,默认 true |
tasks.<name>.result.delimiter |
否 | CSV 分隔符,默认 "," |
tasks.<name>.result.aggregate |
否 | 多行聚合方式:avg、last、min、max,不配置则取最后一行 |
tasks.<name>.result.op_filter |
否 | CSV 算子名匹配模板,支持 {placeholder} 和通配符 |
tasks.<name>.repeat |
否 | 重复次数(CLI --repeat 优先) |
tasks.<name>.repeat_agg |
否 | 重复聚合方式:avg(默认)、avg_without_outliers 或 max(CLI --repeat-agg 优先) |
tasks.<name>.outlier_detection.method |
否 | 异常值检测方法,当前支持 iqr |
tasks.<name>.outlier_detection.max_outlier_ratio |
否 | 异常值比例上限;超过时任务失败 |
tasks.<name>.outlier_detection.iqr_multiplier |
否 | IQR 判定倍数,结合四分位距计算异常值边界 |
tasks.<name>.outlier_detection.min_samples |
否 | 触发异常值分析所需的最小样本数 |
tasks.<name>.steps |
否 | 多步骤配置(见"多步骤任务流程") |
行为说明:当异常值比例大于阈值时,任务失败并输出样本、边界、异常值和比例;当比例不超过阈值时,先移除异常值再求平均;当样本数小于 min_samples 时,跳过异常值分析并直接使用普通平均值。
*使用 steps 时不需要顶层 command
workflows 字段:
| 字段 | 必填 | 说明 |
|---|---|---|
workflows.<name>.tasks |
是 | 任务名称列表,按顺序执行 |
bisect 字段:
| 字段 | 必填 | 说明 |
|---|---|---|
bisect.workflows |
是 | bisect 使用的工作流数组。支持字符串简写或完整对象格式 |
bisect.test_type |
否 | 测试类型(accuracy 或 performance),默认 accuracy。CLI --type 已废弃 |
bisect.post_workflows |
否 | bisect 结束后执行的工作流数组,默认不执行 |
bisect.git_repo |
否 | git 操作目录,默认等于 working_dir |
bisect.regression |
否 | 性能退化阈值百分比,默认 10。CLI --regression 优先 |
bisect.threshold |
否 | 绝对性能阈值,不配置则使用百分比模式。CLI --threshold 优先 |
bisect.repeat |
否 | 每步重复次数,默认 1。CLI --repeat 优先 |
bisect.repeat_agg |
否 | 重复聚合方式:avg(默认)、avg_without_outliers 或 max |
bisect.workflows 数组格式:
每个工作流条目可以是:
- 字符串简写:仅工作流名称,默认
repeatable: true - 完整对象:包含
name和repeatable字段
{
"bisect": {
"workflows": [
"build_pipeline", // 简写格式,repeatable 默认 true
{"name": "test_pipeline", "repeatable": false} // 完整格式
]
}
}
| 字段 | 必填 | 说明 |
|---|---|---|
name |
是 | 工作流名称,必须在 workflows 中定义 |
repeatable |
否 | 是否应用 --repeat 参数,默认 true。设为 false 时强制单次执行 |
bisect.post_workflows 数组格式:
bisect 完成并恢复原始分支后执行的工作流。支持字符串或对象:
{
"bisect": {
"workflows": ["build_test"],
"post_workflows": ["cleanup", "report"]
}
}
执行顺序:所有 bisect 工作流 → 恢复原始分支 → 所有 post_workflows。
向后兼容:
旧格式自动转换:
bisect.workflow: "name"→bisect.workflows: ["name"](显示废弃警告)bisect.build_before_test: true→ 自动生成_bisect_auto工作流(显示废弃警告)bisect.post_workflow: true→ 执行所有 bisect 工作流bisect.post_workflow: "name"→bisect.post_workflows: ["name"]|
全局环境变量(env)
顶层 env 字段定义全局环境变量,所有任务自动继承:
{
"env": {
"http_proxy": "http://proxy.example.com:8080",
"https_proxy": "http://proxy.example.com:8080"
},
"tasks": {
"build": {"command": "bash build.sh"},
"deploy": {
"command": "bash deploy.sh",
"env": {"DEBUG": "1"}
}
}
}
优先级(高到低): step env > task env > 顶层 env > source_env
环境变量注入(source_env)
安装算子后通常需要 source 一个脚本设置环境变量,供任务使用。可在顶层或任务级别配置:
{
"name": "my_repo",
"working_dir": "/path/to/repo",
"tasks": {
"accuracy": {
"source_env": "{install_path}/{commit}/set_env.bash",
"steps": [...]
}
}
}
流程: 执行任务前,框架先 source <script>,捕获新增/修改的环境变量,注入到命令环境中。
- 必须是绝对路径(替换占位符后),相对路径会报错
- 支持
{placeholder}替换(如{install_path}、{commit}) - 任务级别
source_env优先于顶层source_env - 环境变量对所有步骤生效
- 步骤级别的
env配置优先于source_env
占位符
配置中的 command、args、result.path、artifacts 支持占位符,运行时自动替换。
内置占位符:
| 占位符 | 来源 | 说明 |
|---|---|---|
{working_dir} |
配置文件 | 工作目录绝对路径 |
{commit} |
--commit 或自动检测 |
当前 git commit hash(未指定 --commit 时自动获取 HEAD) |
{timestamp} |
自动生成 | 当前时间戳,格式 20260327_103000,用于区分同名文件 |
自定义占位符:
通过配置文件 vars 字段预定义常用变量,避免每次 CLI 传入:
{
"name": "my_repo",
"working_dir": "/path/to/repo",
"vars": {
"install_path": "/usr/local/Ascend",
"target": "ascend910"
},
"tasks": {
"build": {
"command": "bash build.sh",
"args": ["--target={target}"]
}
}
}
也可通过 --arg KEY=VALUE 或 --arg @file.json 在 CLI 传入或覆盖配置中的变量:
# 传入自定义变量
forge build my_repo --arg op_name=matmul --arg target=ascend910
# 从 JSON 文件加载变量
forge build my_repo --arg @vars.json
# 混合 JSON 文件和命令行覆盖
forge build my_repo --arg @common.json --arg target=ascend310
# 快捷方式
# --op → --arg op_name=VALUE
# --cs → --arg case=VALUE
# --ip → --arg install_path=VALUE
forge build my_repo --op matmul
forge test my_repo -t acc --cs case1
forge build my_repo --ip /usr/local/Ascend
# CLI 覆盖配置中的 vars(target 从 ascend910 变为 ascend310)
forge build my_repo --arg target=ascend310
@file.json 只支持扁平 JSON 对象,所有值都必须是字符串;多个 --arg 会按命令行顺序合并,后面的值覆盖前面的值。
最小 JSON 对象示例:
{
"op_name": "matmul",
"target": "ascend910"
}
优先级(高到低): CLI --arg > capture(运行时捕获) > 配置 vars > 内置变量
变量预检查: 执行前自动扫描配置中所有占位符,缺失则报错。通过检查后打印变量表:
Variables:
op_name = matmul
commit = abc1234567890
配置文件中使用:
"tasks": {
"build": {
"command": "bash build.sh",
"args": ["--op", "{op_name}", "--target", "{target}"]
}
}
所有任务命令均支持 --arg 和 --op。若配置中使用了占位符但未通过 CLI 传入,会报错提示。
多步骤任务流程
任务可以由多个步骤组成(如编译 → 安装),使用 steps 列表:
"tasks": {
"build": {
"steps": [
{
"name": "compile",
"command": "bash build.sh",
"args": ["--ops={op_name}"],
"working_dir": ".",
"timeout": 600,
"success_pattern": "Build succeeded",
"artifacts": ["output/libkernel.so"]
},
{
"name": "install",
"command": "bash install.sh",
"working_dir": ".",
"timeout": 120,
"success_pattern": "Install succeeded"
}
]
}
}
规则:
- 步骤按顺序执行,任一步骤失败则整体失败,后续步骤不执行
- 每个步骤可独立设置
command、args、working_dir、timeout、success_pattern、artifacts、capture skip_if_exists:指定产物路径(字符串或数组),支持 glob 和{placeholder},所有文件存在且非空则跳过skip_if_artifacts_exist: true:复用该步骤的artifacts列表作为跳过检查条件artifacts检查在对应步骤执行后进行- 向后兼容:不使用
steps时,原有单command写法不受影响
步骤跳过示例
{
"name": "compile",
"command": "bash build.sh",
"artifacts": ["output/libkernel.so", "output/op_*.bin"],
"skip_if_artifacts_exist": true
}
等价于:
{
"name": "compile",
"command": "bash build.sh",
"skip_if_exists": ["output/libkernel.so", "output/op_*.bin"]
}
产物已存在且非空时输出:Skipped (artifacts exist)
步骤间变量传递(capture)
步骤可以从 stdout 中提取值,存为变量供后续步骤使用:
"steps": [
{
"name": "get version",
"command": "cat version.txt",
"capture": {
"version": "v([0-9.]+)"
}
},
{
"name": "install",
"command": "bash install.sh",
"args": ["--version", "{version}", "--path", "{install_path}"]
}
]
规则:
capture是一个 dict,key 为变量名,value 为正则表达式(第一个捕获组)- 从步骤的 stdout 中匹配,成功后注入到 variables,后续步骤可用
{变量名}引用 - 匹配失败会打印 warning,不中断执行
- 变量预检查时会识别
capture定义的变量,不会误报缺失
输出示例:
Step 1/2: get version
Captured: version = 2.5.1
Step 2/2: install
Command: bash install.sh --version 2.5.1 --path /usr/local
成功判断逻辑
- 检查进程退出码,非 0 即失败
- 若配置了
success_pattern,退出码为 0 时额外匹配 stdout,不匹配也判定失败- 字符串:单个正则匹配
- 数组:所有正则都需匹配(AND 逻辑),如
["Build succeeded", "Install succeeded"]
- 若配置了
artifacts,检查每个产物文件存在、非空、且修改时间在本次编译之后 - 以上均为可选,不配置则仅依赖退出码
结果提取
精度测试和性能测试统一使用 result 配置块,支持两种方式:
从标准输出提取:
{
"result": {
"type": "stdout",
"pattern": "accuracy: ([0-9.]+)"
}
}
从 CSV 文件提取:
{
"result": {
"type": "file",
"path": "output/result.csv",
"format": "csv",
"value_column": 3,
"op_column": 0,
"header": true,
"delimiter": ",",
"aggregate": "avg"
}
}
聚合方式(aggregate 字段): 同一算子有多行数据时的聚合策略:
| 值 | 说明 |
|---|---|
avg |
平均值 |
last |
最后一行 |
min |
最小值 |
max |
最大值 |
| 不配置 | 取最后一行(向后兼容) |
算子名通配符匹配: --op 支持 fnmatch 通配符(*、?、[seq]):
# 匹配所有 matmul 变体
forge test my_repo --type performance --op "matmul*"
# 匹配 add_v1, add_v2(不匹配 add_v10)
forge test my_repo --type performance --op "add_v?"
结果提取示例
多步骤任务中,result 配置放在需要提取结果的步骤上(通常是最后一步):
"tasks": {
"accuracy": {
"steps": [
{
"name": "generate input",
"command": "python gen_input.py",
"args": ["--op", "{op_name}"],
"working_dir": "tests/"
},
{
"name": "run operator",
"command": "bash run_op.sh",
"args": ["{op_name}"],
"working_dir": "."
},
{
"name": "compare result",
"command": "python compare.py",
"args": ["--op", "{op_name}"],
"working_dir": "tests/",
"success_pattern": "PASS",
"result": {
"type": "stdout",
"pattern": "accuracy: ([0-9.]+)"
}
}
],
"timeout": 300
}
}
## CLI 使用
全局选项必须放在子命令前面:
```bash
forge [--config-dir PATH] [-v/--verbose] <command> [options]
短选项速查
| 短选项 | 长选项 | 适用命令 |
|---|---|---|
-v |
--verbose |
全局 |
-t |
--type |
test, run(bisect 已废弃,使用 bisect.test_type 配置) |
-c |
--commit |
build, test, run |
-s |
--step |
build, run |
-b |
--baseline |
test, run |
-w |
--workflow |
bisect |
-g |
--good |
bisect |
-b |
--bad |
bisect |
--type 支持缩写:acc = accuracy,perf = performance。
Daemon 和 Task 子命令
| 命令 | 说明 |
|---|---|
forge daemon start [--foreground] |
启动 daemon(后台运行) |
forge daemon stop |
停止 daemon |
forge daemon status |
查看 daemon 状态和任务统计 |
forge daemon install |
安装 systemd 服务(需 sudo) |
forge daemon uninstall |
卸载 systemd 服务(需 sudo) |
forge task list [--all|--running|--completed] |
列出任务 |
forge task show <id> [--tail N] [--follow] |
查看任务输出 |
forge task cancel <id> |
取消任务 |
forge task resume <id> |
恢复被中断的任务 |
查看配置
# 列出所有已配置的算子仓
forge list
# 查看某个仓库的完整配置
forge show my_repo
# 校验配置文件是否合法
forge validate my_repo
# 使用自定义配置目录
forge --config-dir /path/to/configs list
迁移旧配置
如果配置文件使用旧格式(repo_path、build、tests),可一键迁移到新格式:
# 迁移配置目录下所有 JSON 文件
forge migrate
# 预览变更(不修改文件)
forge migrate --dry-run
# 使用自定义配置目录
forge migrate --config-dir /path/to/configs
迁移内容:
-
路径字段迁移:
repo_path→working_dir{repo_path}占位符 →{working_dir}test_path→ 移入vars.test_path
-
任务格式迁移:
build→tasks.buildtests.accuracy→tasks.accuracy(无test_前缀)tests.performance→tasks.performancetests.source_env→ 移除(需在具体任务中配置source_env)
-
Workflow 自动生成:
bisect.build_before_test: true→ 自动生成_bisect_defaultworkflow- 列表格式 workflow
["a", "b"]→ 对象格式{"steps": ["a", "b"]} bisect.post_workflow: true→ 具体名称(如accuracy_pipeline)
-
Bisect 配置迁移(新):
bisect.workflow: "name"→bisect.workflows: ["name"](数组格式)bisect.post_workflow: "name"→bisect.post_workflows: ["name"](数组格式)- 添加
bisect.test_type字段(从 CLI--type参数移入配置)
迁移示例输出:
example-build-base.json (migrated):
- repo_path → working_dir
- build → tasks.build
- tests.accuracy → tasks.accuracy
- tests.performance → tasks.performance
- bisect.workflow → bisect.workflows (array format)
- added bisect.test_type: accuracy
5 change(s) applied.
编译
# 编译当前 HEAD
forge build my_repo
# 编译指定 commit(自动 stash 未提交更改,编译后恢复)
forge build my_repo --commit abc123
# 编译指定算子
forge build my_repo --op matmul
# 传入多个自定义参数
forge build my_repo --arg op_name=matmul --arg target=ascend910
# 只执行指定步骤(多步骤配置时)
forge build my_repo --step install # 只安装,跳过编译
forge build my_repo --step compile # 只编译,跳过安装
测试
# 精度测试
forge test my_repo --type accuracy
# 性能测试
forge test my_repo --type performance
# 测试特定算子
forge test my_repo --type accuracy --op matmul
# 在指定 commit 上测试(自动编译)
forge test my_repo --type performance --commit abc123
# 与指定 commit 的历史结果对比
forge test my_repo --type performance --baseline abc123
# 与上次保存的结果对比
forge test my_repo --type performance --compare-last
# 性能测试跑 3 次取平均值
forge test my_repo -t perf --op matmul --repeat 3
# 性能测试跑 3 次取最大值
forge test my_repo -t perf --op matmul --repeat 3 --repeat-agg max
编译+测试(run)
一个命令完成 build → test,build 失败则不执行 test。
# 编译后跑精度测试
forge run my_repo --type accuracy --op matmul
# 编译后跑性能测试,并与上次结果对比
forge run my_repo --type performance --op matmul --compare-last
# 在指定 commit 上编译+测试
forge run my_repo --type accuracy --commit abc123
# 只执行指定编译步骤后测试
forge run my_repo --type accuracy --step install
自定义任务
配置文件中可通过 tasks 定义任意名称的任务:
{
"tasks": {
"deploy": {
"command": "bash deploy.sh",
"artifacts": ["lib/libkernel.so"]
},
"lint": {
"steps": [
{"name": "check", "command": "flake8 .", "success_pattern": "0 errors"},
{"name": "format", "command": "black --check ."}
]
}
}
}
# 运行自定义任务
forge task-run my_repo deploy
forge task-run my_repo lint
# 支持所有通用选项
forge task-run my_repo deploy --arg key=val --op matmul
自定义任务支持所有步骤特性:command、args、working_dir、timeout、env、success_pattern、artifacts、result、capture、skip_if_exists、steps。
向后兼容: 旧的 build 和 tests 配置自动映射为任务(build → build,tests.accuracy → test_accuracy)。forge build、forge test、forge run、forge bisect 命令不受影响。
Workflow(任务编排)
通过 workflows 定义多个任务的串行执行序列,支持步骤间变量传递:
{
"tasks": {
"build": {"command": "bash build.sh"},
"setup_env": {
"command": "bash setup_test_env.sh",
"capture": { "test_env_path": "ENV_PATH=(.+)" }
},
"test_accuracy": {
"command": "python run_test.py",
"args": ["--env={test_env_path}"]
}
},
"workflows": {
"full_pipeline": {
"steps": ["build", "setup_env", "test_accuracy"]
},
"test_only": {
"steps": ["test_accuracy"]
}
}
}
# 运行 workflow
forge workflow my_repo full_pipeline
forge workflow my_repo test_only --arg op_name=matmul
按顺序执行,任一任务失败则停止。前序步骤通过 capture 提取的变量自动传递给后续步骤。
向后兼容: 旧的列表格式 "ci": ["build", "test"] 自动转换为 "ci": {"steps": ["build", "test"]},并显示迁移提示。
Bisect 问题定位
在 good 和 bad 两个 commit 之间自动二分查找引入问题的 commit。使用 bisect.workflows 数组定义每步的执行流程。
配置示例:
{
"bisect": {
"test_type": "accuracy",
"workflows": ["build_test"],
"post_workflows": ["cleanup"],
"regression": 15.0
}
}
CLI 使用:
# 精度 bisect(test_type 从配置读取)
forge bisect my_repo --good abc123 --bad def456
# 性能 bisect(需在配置中设置 test_type: "performance")
forge bisect my_repo --good abc123 --bad def456 --op matmul
# 自定义退化阈值(默认 10%,配置或 CLI 指定)
forge bisect my_repo --good abc123 --bad def456 --regression 20
# 使用绝对阈值(耗时超过 15 即判定为 bad)
forge bisect my_repo --good abc123 --bad def456 --threshold 15
# 重复测试以减少波动(仅对 repeatable=true 的工作流生效)
forge bisect my_repo --good abc123 --bad def456 --repeat 3 --repeat-agg avg
# 指定工作流(覆盖配置)
forge bisect my_repo --good abc123 --bad def456 --workflow custom_pipeline
废弃提示: --type/-t 已废弃。测试类型应在配置文件的 bisect.test_type 字段设置。使用 CLI --type 时会显示警告。
Bisect 流程:
- 获取 good..bad 之间的 commit 列表
- 性能测试时,先在 good commit 上运行最后一个 workflow 获取基线值
- 二分查找:checkout → 按顺序执行 workflows 数组 → 判断 good/bad
- 精度 bisect:退出码 + success_pattern 判断
- 性能 bisect:与基线对比,超过退化阈值判定为 bad
- 非最后一个 workflow 失败 → 跳过该 commit
- 跳过超过总步数 50% 时中止
- 完成后自动恢复原始分支 → 执行 post_workflows
多工作流执行:
bisect.workflows 数组中的工作流按顺序执行:
- 前序工作流失败 → 跳过当前 commit(不计入 good/bad 判断)
- 最后一个工作流失败 → 根据失败类型决定(精度测试失败为 bad,其他失败为 skip)
repeatable=true的工作流会应用--repeat参数
配置优先级: CLI --workflow 覆盖配置 bisect.workflows[0](单工作流模式)
环境变量
| 变量 | 说明 |
|---|---|
FORGE_CONFIG_DIR |
配置文件目录路径,等价于 --config-dir |
后台任务(Daemon 模式)
Daemon 是一个常驻的后台进程,管理和执行提交的后台任务,支持任务持久化和自动恢复。
启动和停止
# 启动 daemon(后台运行,自动 fork)
forge daemon start
# 前台运行(调试用)
forge daemon start --foreground
# 停止 daemon
forge daemon stop
# 查看状态
forge daemon status
提交后台任务
任意命令加上 --daemon 即可后台运行:
# 后台编译
forge build my_repo --daemon
# 后台测试
forge test my_repo --type accuracy --daemon
# 后台 bisect
forge bisect my_repo --good abc --bad def --type accuracy --daemon
提交后立即返回 task_id:Task submitted: task_abc123 (running in background)
管理任务
# 查看运行中的任务(默认)
forge task list
# 查看所有任务
forge task list --all
# 查看已完成的任务
forge task list --completed
# 取消任务
forge task cancel task_abc123
# 恢复被中断的任务
forge task resume task_abc123
查看任务输出
# 查看累积输出(默认最近 100 行)
forge task show task_abc123
# 指定行数
forge task show task_abc123 --tail 50
# 实时跟踪(Ctrl+C 停止)
forge task show task_abc123 --follow
输出文件保存在 ~/.forge/logs/task_{task_id}.log,任务结束后保留。
自动恢复
Daemon 重启后自动恢复被中断的任务(最多重试 3 次)。
systemd 服务
# 安装为系统服务(需 root)
sudo forge daemon install
# 卸载服务
sudo forge daemon uninstall
安装后 daemon 随系统自动启动。
结果存储
测试结果自动保存到 ~/.forge/results/<repo_name>/,JSON 格式:
{
"repo": "my_repo",
"commit": "abc1234",
"timestamp": "2026-03-23T10:00:00",
"type": "performance",
"results": {
"matmul": 12.3,
"add": 0.8
}
}
可通过 --compare-last 或 --baseline 与历史结果对比。
日志系统
每次编译和测试的完整输出自动保存到日志文件,方便问题定位。
日志文件位置
~/.forge/logs/<repo_name>/
├── build_2026-03-24T10-30-00.log
├── test_accuracy_2026-03-24T10-35-00.log
└── test_performance_2026-03-24T10-40-00.log
日志内容
每个日志文件包含:
- 执行时间、完整命令、工作目录
- 退出码、是否超时、是否成功
- 编译/测试脚本的 完整 stdout 和 stderr
屏幕输出
# 默认模式:打印执行的命令和工作目录,失败时打印 stderr
forge build my_repo
# verbose 模式:实时逐行打印脚本的 stdout/stderr
forge --verbose build my_repo
forge --verbose test my_repo --type accuracy
排查编译/测试失败
- 加
--verbose查看实时输出:forge --verbose build my_repo - 查看日志文件:
cat ~/.forge/logs/my_repo/build_*.log - 检查日志中的 stderr 和退出码
- 对比手动执行时的环境变量(配置文件中
tasks.build.env是否缺失关键变量)
扩展
- 新增算子仓:在
configs/下添加一个 JSON 文件即可,无需改代码 - 新增任务:在配置文件的
tasks下新增 key(如stress),框架通用处理 - 新增结果文件格式:在
tester.py的extract_result_from_file中扩展解析器 - 新增任务类型:继承
TaskRunner,覆盖_post_step()和_make_result()即可。执行引擎(单步/多步、skip、capture、日志等)自动继承
开发
# 运行测试
source .venv/bin/activate
python -m pytest tests/ -v
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ascend_forge-0.1.2.tar.gz.
File metadata
- Download URL: ascend_forge-0.1.2.tar.gz
- Upload date:
- Size: 333.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
44cbff288b27daed64e8c615dac77782a691e2ae34dc2337f090d4c93d0e0a3b
|
|
| MD5 |
142e045fbd037c087bfaaef84b1994f6
|
|
| BLAKE2b-256 |
aad0100a0f32c3f4bf2eae00b3bc05ca9f002457c78af7682e3fd7be3362a7d3
|
File details
Details for the file ascend_forge-0.1.2-py3-none-any.whl.
File metadata
- Download URL: ascend_forge-0.1.2-py3-none-any.whl
- Upload date:
- Size: 279.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c273f0b8c8b864d22ce08dad0bf0324e04c76bc4c4b5cce53ec75f88724d8194
|
|
| MD5 |
0ec313a6f1e44770b3be76cbb84984eb
|
|
| BLAKE2b-256 |
c97a8d91a24a5c6ed9c44dc9ea32e75def4ec310d28d8d2a8e15e6d0bd894058
|