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"]},并显示迁移提示。
参数列表循环
task-run、workflow 和 run 支持通过 --loop KEY=VALUE 对同一个参数的一组值依次执行:
forge task-run my_repo bench --loop op_name=MatMul --loop op_name=PromptFlashAttention
forge workflow my_repo perf_pipeline --loop op_name=MatMul --loop op_name=PromptFlashAttention
forge run my_repo -t performance --loop op_name=MatMul --loop op_name=PromptFlashAttention
规则:
- 多个
--loop必须使用同一个参数名。 - loop 参数优先于同名
--arg。 repeat在每个 loop value 内独立生效。- 结果 key 会带上 loop value 前缀,例如
MatMul/value。
Web UI 的 New Run 页面提供 Loop 区域:选择一个变量名,并在多行输入框中每行填写一个值。
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
Release files for ascend-forge 0.1.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| ascend_forge-0.1.4.tar.gz | 356.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ascend_forge-0.1.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 652.4 kB
Release files / ascend_forge-0.1.4.tar.gz
| Download URL | ascend_forge-0.1.4.tar.gz |
|---|---|
| Size | 356.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f98a48367f160fa350fbf16e24eb5cbaf3afecbd61676922e5be9c77a83f9ed8
|
|
BLAKE2b-256 checksum How to use checksums |
a1988453016553a00f39525c59e1b36136a8e9da18dd0da412d20e85363451b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|
Release files / ascend_forge-0.1.4-py3-none-any.whl
| Download URL | ascend_forge-0.1.4-py3-none-any.whl |
|---|---|
| Size | 295.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
13d5190a04be8505f11ca613c1e3c9db3e6516b44526af4abfcbc53bb00cffb0
|
|
BLAKE2b-256 checksum How to use checksums |
c1c194eaf423148a896a2bed95deb09534db086657b397c966a87e217f1f8a0a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.9
|