Merge pull request #107 from NCIC-AlphaSparse/main version ci checks
Merge pull request #107 from NCIC-AlphaSparse/main
version ci checks
GPU 稀疏运算库(SpMV、SpMM、SpGEMM、SDDMM、gather、scatter、多种稀疏格式)。
要在非 NVIDIA 加速卡上做 bring-up? 从 prompt.md 开始,再读 docs/<后端>.md(那台机器怎么跑)和 modified/<后端>.md(前人改了什么、为什么)。 本文记录的是 CUDA 参照路径。
prompt.md
docs/<后端>.md
modified/<后端>.md
pip install . --no-deps --no-build-isolation
离线时可加 --no-build-isolation 避免拉取构建依赖。
--no-build-isolation
运行时依赖(按需安装):
pip install torch triton cupy-cuda12x
交付物就是这一轮跑出的 summary.json:conf/operators.yaml 里登记的 20 个交付变体 (delivery_variants:gather、scatter 的 f16/f32/f64/c32/c64,以及 spmv_csr、spmv_coo、spmm_csr、 spmm_coo、sddmm_csr 的 f32/f64)的精度和性能, 性能测 10 个 MatrixMarket 矩阵(conf/operators.yaml 的 delivery_matrices),热身 5 次、计时 20 次。 --benchmark-input 仍然给装有那 30 个 .mtx 的目录:--delivery-only 会自动只保留清单里的 10 个, 不需要额外参数;目录里缺其中任何一个时(比如用 tests/data 做冒烟、或拷贝不全)不做过滤, 并在最开头几行打印说明。各后端用同一条命令, 下表列出各后端要改的地方,完整做法见各 docs/<后端>.md 的”交付复现”一节。
summary.json
conf/operators.yaml
delivery_variants
delivery_matrices
--benchmark-input
.mtx
--delivery-only
tests/data
export PYTHONPATH=$PWD/src python3 -c "import flagsparse; print(flagsparse.__file__)" # 必须是 <仓库>/src/flagsparse/__init__.py timeout -s KILL 21600 python3 run_flagsparse_pytest.py \ --phase both --mode normal --delivery-only --gpus 0 --timeout 3600 \ --benchmark-input <30 个 .mtx 所在目录> --benchmark-warmup 5 --benchmark-iters 20 \ --results-dir pytest_results_<后端>_delivery python3 tools/delivery_table.py pytest_results_<后端>_delivery # 打印 20 行结果表,缺变体时退出码为 1
non
--mode normal
quick
--timeout 3600
0
timeout -s KILL
pip install cupy-cuda12x
pip install hip-python
FLAGSPARSE_BACKEND=metax FLAGSPARSE_MACA_VENDOR=torch
--op-benchmark-args='sddmm_csr=--no-cusparse'
--timeout 4500
FLAGSPARSE_BACKEND=mthreads
run_flagsparse_split_delivery.py
set_env.sh
FLAGSPARSE_BACKEND=ascend FLAGSPARSE_ASCEND_VENDOR=torch
--gpus 6,7
spmv_coo
spmm_coo
FLAGSPARSE_BACKEND=xpu FLAGTREE_BACKEND=xpu TRITON_BACKEND=xpu
FLAGSPARSE_BACKEND=iluvatar FLAGSPARSE_ILUVATAR_VENDOR=cupy_cusparse
86a09cd(2026-09-18)之前跑出的结果不能拿来比较:旧版把 int64、trans/conj 的行也平均进了 ..._int_non 变体,还把没有加速比的行当作 0。请用当前 runner 重跑,见 prompt.md 第 2 节。
86a09cd
..._int_non
summary.json 里各状态的含义:Passed / Failed 为实测结果;Timeout 表示算子跑了但触发了 --timeout;NotFound 表示没有该变体的行(没跑,或本后端没有配置);NoBaseline(C API)表示 内核跑通且精度通过,只是厂商库没有这个 dtype/算子可比。CUDA 上(RTX 5090,2026-09-17,sweep 收窄之前,当时的清单是 40 个变体)全程 79 分钟,最慢的是 SpSV 和 SpGEMM,各约 20 分钟; 这两个现在都不在 20 个变体的清单里,整份清单还没有完整计时过。
Passed
Failed
Timeout
--timeout
NotFound
NoBaseline
精度阶段的 Skipped:有通过、无失败时,只因“能力边界”而跳过的用例不会把状态降成 Skipped, 它们仍计入 skipped 并列在 details.skipped 里。目前豁免的只有两条原因 (run_flagsparse_pytest.py 的 EXPECTED_ACCURACY_SKIP_REASONS):外部矩阵目录未配置、legacy bucket 只支持 int32 列索引。其它原因的跳过仍记 Skipped,全部用例都跳过(没有一个通过)也记 Skipped。 新 CSR 算法在没有验证过 profile 的后端(MetaX、XPU)上不是靠豁免:test_spmv_csr_accuracy.py 只参数化该后端有 profile 的算法(list_spmv_csr_algorithms(backend=...)),不会收集也就不会跳过, 交付行由真正跑起来的旧算法用例支撑。看一行 Passed 背后有多少用例,要看它的 passed 数, 不要只看状态。
Skipped
skipped
details.skipped
run_flagsparse_pytest.py
EXPECTED_ACCURACY_SKIP_REASONS
test_spmv_csr_accuracy.py
list_spmv_csr_algorithms(backend=...)
passed
FlagSparse 按检测到的运行时对厂商参考实现与基线进行分发;Triton 内核本身在各后端保持不变。
torch.version.hip is None
cupy-cuda12x
torch.version.hip is not None
hip-python
_detect_maca_runtime()
torch
torch.musa
torch.sparse
torch.npu
torch_xmlir
torch_xpu
torch_gcu
_detect_iluvatar_runtime()
+corex
torch.cuda
后三个没有自己的算子内核:backends/{xpu,gcu,iluvatar}/ 下只有 __init__.py,走共享实现。天数和 MetaX 一样是 CUDA 兼容栈, 占用的是原来寒武纪 mlu 备用槽位的位置。 昆仑芯那条”插件必须可 import”不是多余的谨慎 —— 上游 PyTorch 给 Intel GPU 也装了 torch.xpu 命名空间,只看命名空间会把一块 Intel 卡认成昆仑芯。
backends/{xpu,gcu,iluvatar}/
__init__.py
mlu
torch.xpu
⚠️ 摩尔线程与昇腾不是 CUDA 兼容的:torch 把它们暴露成独立设备类型 (musa / npu),torch.cuda.* 和 Tensor.is_cuda 都不适用。 设备抽象迁移已完成:算子模块里不再有任何 torch.cuda.* 直接调用, 一律走 _ACCEL.* 和 _is_accel_tensor();仅剩的 11 处在 _common.py 自己的运行时 探测里(设备名判定与 OOM 兜底)。在 CUDA / ROCm / MACA 上 _ACCEL is torch.cuda, 因此对这三个后端是逐字等价,内核一行未改。tests/ 下直接跑的 benchmark 脚本 从 tests/benchmark_utils.py 取同一对名字。
musa
npu
torch.cuda.*
Tensor.is_cuda
_ACCEL.*
_is_accel_tensor()
_common.py
_ACCEL is torch.cuda
tests/
tests/benchmark_utils.py
MACA 与 CUDA 源码兼容,机器上 torch.version.cuda 有值而 torch.version.hip 为 None, 靠 ROCm 那套判据分不出 MetaX 和 NVIDIA。检测按顺序尝试:FLAGSPARSE_BACKEND 环境变量、 MetaX 专有的 torch.version 属性、MACA SDK 环境变量(MACA_PATH / MACA_HOME)、 设备名(先认厂商串,再认 c550 / c500 型号串)。 在真机上先显式指定,等自动探测确认无误后再依赖它:
torch.version.cuda
torch.version.hip
None
FLAGSPARSE_BACKEND
torch.version
MACA_PATH
MACA_HOME
c550
c500
export FLAGSPARSE_BACKEND=metax # cuda | rocm | metax | mthreads | ascend | xpu | gcu | iluvatar export FLAGSPARSE_MACA_MODEL=c550 # 覆盖型号检测 export FLAGSPARSE_MACA_VENDOR=torch # CuPy 不可用时用 PyTorch 作基线;none = 不要基线 # 摩尔线程 / 昇腾的基线选择 export FLAGSPARSE_MTHREADS_VENDOR=none # none(默认)| torch | musparse export FLAGSPARSE_ASCEND_VENDOR=torch # torch(默认)| ops_sparse | none export FLAGSPARSE_XPU_VENDOR=torch # torch(默认)| none # 正确性参考。CUDA 与 ROCm 比对各自的厂商库加 torch;其余后端一律比对 CPU 上的 SciPy —— # 那些平台上的 torch.sparse 本身就是被测对象,不是参考。在 CUDA 机器上强制 "scipy", # 是这条路径在送到没人能跑的硬件之前唯一的验证办法。 export FLAGSPARSE_ACCURACY_REFERENCE=auto # auto(默认)| scipy | torch
调优参数按型号分档,在 spmv_csr.py 的 _MACA_SPMV_PROFILES 和 spsv.py 的 _MACA_SPSV_PROFILES。目前只有 C550(FlagTree metax 后端的参考型号)一档, 内容是从 CUDA 平移的;识别不出的型号会回落到它。每个参数旁注了 gfx936 上实测的 ROCm 值,是有意不继承的。
spmv_csr.py
_MACA_SPMV_PROFILES
spsv.py
_MACA_SPSV_PROFILES
在 DCU/ROCm 机器上,安装与 ROCm 版本匹配的 hip-python:
两种绑定都是可选的。若都不可用,基准测试会回退到通用的 torch.sparse 参考实现, 并在 *_reason / backend_status 字段中给出原因,而不是直接报错。
*_reason
backend_status
分发逻辑位于各 _*_sparse_ref_backend() 辅助函数,返回 ("hipsparse" | "cupy_cusparse" | None, reason):
_*_sparse_ref_backend()
("hipsparse" | "cupy_cusparse" | None, reason)
flagsparse.sparse_operations._common
.spmm_csr
.spmm_coo
.spgemm_csr
.gather_scatter
所有命令都要带 PYTHONPATH=src。开工先确认没跑到旧的已安装包 —— 这是 DCU 上最容易踩的坑:
PYTHONPATH=src
python -c "import flagsparse; print(flagsparse.__file__)" # 必须指向 <仓库>/src/flagsparse/__init__.py
1. 先 diagnose,再跑基准。 hipSPARSE 用错时是挂住而不是报错,所以要逐级探, 不要一上来就 --op all:
--op all
python tests/diagnose_hipsparse_ref.py --op env # 先探环境,不碰任何算子 python tests/diagnose_hipsparse_ref.py --timing-only # HIP 事件计时链 python tests/diagnose_hipsparse_ref.py --op spmv-csr # 再一次一个算子 python tests/diagnose_hipsparse_ref.py --op all # 单点全部通过后才跑这个
2. 正确性套件。
PYTHONPATH=src python -m pytest tests/pytest -q
SpSV 和 SpSM 目前在 DCU 上会 GPU 内核死锁(见 docs/DCU.md 已知限制一节),需要排除掉才能跑完:
PYTHONPATH=src python -m pytest tests/pytest -q \ --ignore=tests/pytest/test_spsv_csr_accuracy.py \ --ignore=tests/pytest/test_spsv_coo_accuracy.py \ --ignore=tests/pytest/test_spsv_sell_accuracy.py \ --ignore=tests/pytest/test_spsm_accuracy.py
DCU 基准线:排除 851 个 SpSV/SpSM 用例后 984 passed / 1 failed,约 60 秒。 那个失败是 spmv_coo / spmv_csc 的容差抖动 —— 每次失败的 dtype 参数都不一样, 且单独跑就过;参数固定不变的失败才是真问题。CUDA 全量基准线:1613 passed / 3 failed。
984 passed / 1 failed
spmv_csc
1613 passed / 3 failed
3. 策略/契约类测试 —— 不需要 GPU,秒级:
python -m pytest tests/ci -q # 判据:0 failed(通过数随新增测试增长, # 2026-09-19 为 102 passed / 3 skipped)
4. 逐算子基准:
M=matrix # 任意 .mtx 目录 python tests/test_spmv.py $M --warmup 2 --iters 5 python tests/test_spmm.py $M --warmup 2 --iters 5 python tests/test_spgemm.py $M --warmup 2 --iters 5 python tests/test_spmm_coo.py $M --warmup 2 --iters 5
看时间数据前先确认没有别的任务在争抢 GPU。
5. 统一运行器。 交付测试用复现交付测试一节的命令。 其中的 --timeout 3600 保证卡住的算子不会让整轮停摆:该算子记为 Timeout,然后继续往下跑。 在 DCU 上会死锁的 SpSV/SpSM 已不在交付清单里,但显式 --ops spsv_csr,... 仍会跑到它们; 那时 --gpus 0,1 单独用没有用 —— 它只是把算子分成两条队列,含 SpSV/SpSM 的那条照样要等到超时。
--ops spsv_csr,...
--gpus 0,1
DCU 上的完整验证流程(环境检查、旧安装包陷阱、如何确认真的走了 hipSPARSE、 已知限制、排查速查表)见 docs/DCU.md。
交付测试(20 个变体)用复现交付测试一节的命令, 按表中沐曦那一行设置;确切命令见 docs/MACA.md 0.5 节。
下面这条是另一回事:连同 CSC、BSR 等其他算子一起的全量 sweep,PyTorch 基线,30 个 MatrixMarket 矩阵。由于当前内核在该平台可能卡住,暂不包含 SpSV 和 SpSM;SpMM BELL 也暂时 排除——单个矩阵的耗时可能超过其余算子之和:
PYTHONPATH=src python -u run_flagsparse_pytest.py --phase both --mode quick --gpus 0 \ --ops gather,scatter,spmv_csr,spmv_coo,spmv_csc,spmv_bsr,spmm_csr,spmm_coo,spmm_bsr,spmm_csc,spgemm_csr,sddmm_csr \ --benchmark-input /root/gcx/matrix --benchmark-warmup 5 --benchmark-iters 20 \ --op-benchmark-args='sddmm_csr=--no-cusparse' --op-benchmark-args='spmv_bsr=--resume' \ --timeout 7200 --results-dir pytest_results_metax_runner_both_w5_i20
--benchmark-args 会追加到所有性能脚本;仅某个算子支持的参数使用可重复的 --op-benchmark-args=算子名=参数。上例只向 BSR 脚本传入 --resume,不会影响其他算子; 参数部分含空格时再整体引用,例如 --op-benchmark-args="spmv_bsr=--dtypes float64"。 BSR 脚本会保留已完成的 PASS/FAIL case、重试此前的 ERROR case, 并且只对精度为 PASS 的行给出 bsr_speedup_vs_pytorch。
--benchmark-args
--op-benchmark-args=算子名=参数
--resume
--op-benchmark-args="spmv_bsr=--dtypes float64"
PASS
FAIL
ERROR
bsr_speedup_vs_pytorch
结果目录包含各算子的精度、性能文件和合并汇总。后端检查、基线说明和 C550 已知限制见 docs/MACA.md。
在 MetaX 上,test_spmm_csc.py 使用 PyTorch 原生 CSC 作为性能基线:直接构造 torch.sparse_csc_tensor 后调用 torch.sparse.mm。CSC 格式构造不计入计时,CSV 中记录为 pytorch_ms,并计算 triton_speedup_vs_pytorch。--no-cusparse 只关闭可选的厂商基线, 不会关闭 PyTorch CSC 基线;COO 路径仍只用于精度参考。
test_spmm_csc.py
torch.sparse_csc_tensor
torch.sparse.mm
pytorch_ms
triton_speedup_vs_pytorch
--no-cusparse
只能使用 6、7 号 NPU。交付测试用复现交付测试一节的命令, 按表中昇腾那一行设置;确切命令、以 PyTorch-NPU 为基线的 5 个算子(其余只做能力探测)、 环境检查和已知限制见 docs/ASCEND.md。
src/flagsparse/
sparse_operations/
sparse_operations/backends/<后端>/
gather_f32_int
spmv_csr_f32_int_non
tools/delivery_variants.py
summary.csv
result.html
tests/pytest/
tests/ci/
tests/*.py
benchmark/
capi/
docs/
docs/README.md
modified/
在项目根目录执行,或先 cd tests 再运行脚本(.mtx 目录可用 ../matrix 等相对路径)。
cd tests
../matrix
算子测试 runner - 按 YAML 算子清单逐算子运行精度/性能测试:
python run_flagsparse_accuracy.py --list-ops python run_flagsparse_accuracy.py --mode quick --gpus 0 python run_flagsparse_performance.py --ops spmv_csr,spmm_csr --benchmark-input matrix --benchmark-warmup 5 --benchmark-iters 20 python run_flagsparse_pytest.py --phase both --mode quick --gpus 0,1 --benchmark-input matrix --results-dir pytest_results
默认情况下,run_flagsparse_accuracy.py 和 run_flagsparse_performance.py 从 conf/operators.yaml 读取算子 id,可用 --stages 过滤,并按 --gpus 把算子分配到不同 GPU。需要一个命令同时跑两个阶段时,仍可使用 run_flagsparse_pytest.py --phase both。--ops 和 --op-list 会覆盖 YAML 选择。默认全量测试会排除手工测试项 alpha_spmm_alg1 和 spmv_coo_tocsr;需要运行时用 --ops 或 --op-list 显式指定。spsv_descriptor_api、sparse_format_constructors 这类辅助接口不是算子测试项。
run_flagsparse_accuracy.py
run_flagsparse_performance.py
--stages
--gpus
run_flagsparse_pytest.py --phase both
--ops
--op-list
alpha_spmm_alg1
spmv_coo_tocsr
spsv_descriptor_api
sparse_format_constructors
精度阶段会启动 pytest tests/pytest -m <operator marker> --mode quick|normal --record json --output <op>/accuracy_result.json,使用合成 CUDA 数据。性能阶段会按算子启动对应的 tests/test_*.py benchmark 命令;依赖 MatrixMarket 矩阵的命令接收 --benchmark-input(默认 tests/data,本地矩阵目录可传 matrix),CSV 输出也会规范化成 FlagGems 风格的 <op>/performance_result.json。结果默认写入 pytest_results_<timestamp>/,也可通过 --results-dir 指定。每个算子目录在对应阶段运行后包含 accuracy_stdout.log、accuracy_stderr.log、accuracy_result.json、accuracy_detail.json、performance_stdout.log、performance_stderr.log、performance.csv、performance_result.json 和 performance_detail.json。根目录 summary.json 使用 FlagGems 的 timestamp / env / result 结构。GPU id、命令、日志、totals、pytest case 明细和规范化 benchmark 记录等 FlagSparse 扩展字段保存在 summary_flat.json 和各算子的 *_detail.json 中。summary.csv 和可选 summary.xlsx 用于表格查看,并会自动生成可在浏览器查看的 result.html。自动生成的 result.html 使用 summary_flat.json 渲染;summary.json 保持为面向外部工具的精简 FlagGems 兼容汇总。
pytest tests/pytest -m <operator marker> --mode quick|normal --record json --output <op>/accuracy_result.json
tests/test_*.py
matrix
<op>/performance_result.json
pytest_results_<timestamp>/
--results-dir
accuracy_stdout.log
accuracy_stderr.log
accuracy_result.json
accuracy_detail.json
performance_stdout.log
performance_stderr.log
performance.csv
performance_result.json
performance_detail.json
timestamp
env
result
summary_flat.json
*_detail.json
summary.xlsx
直接运行 pytest 精度测试 - 面向开发调试的小规模正确性用例,可按 marker 选择:
pytest tests/pytest --mode quick pytest tests/pytest --mode normal -m "spmv_csr or spmm_csr" pytest tests/pytest --mode quick -m "spmv_coo_tocsr"
新增或修改算子测试项时,需要同步维护算子实现/API 注册、conf/operators.yaml 注册、pytest.ini marker、精度测试、性能命令以及公开替换/导出注册。
pytest.ini
test_spmv.py - CSR SpMV(SuiteSparse .mtx、合成数据或 CSR CSV):
python tests/test_spmv.py <目录或文件.mtx> # 批量跑,默认 float32 python tests/test_spmv.py <目录/> --dtype float64 # 可选:--index-dtype int32|int64、--warmup、--iters、--no-cusparse python tests/test_spmv.py --synthetic # 合成基准 python tests/test_spmv.py <目录/> --csv-csr results.csv # 全部 value×index dtype 写入一个 CSV(运行过程中逐矩阵打印)
test_spmv_coo.py - COO SpMV(需 --synthetic 或 --csv-coo,不能单独批量跑 .mtx):
--synthetic
--csv-coo
python tests/test_spmv_coo.py --synthetic python tests/test_spmv_coo.py <目录/> --csv-coo out.csv
test_spmv_opt.py - SpMV 基线 vs 优化对比(仅 float32 / float64):
float32
float64
python tests/test_spmv_opt.py <目录或文件.mtx> [...] python tests/test_spmv_opt.py <目录/> --csv out.csv
test_spmv_bsr.py - 原生 BSR SpMV,输出按 block-grid padding:
python tests/test_spmv_bsr.py --synthetic --ops non,trans,conj python tests/test_spmv_bsr.py <目录/> --csv-bsr out.csv --block-dims 2,4 --ops non,trans,conj --alg compare # correctness 使用 BSR 展开的 COO 作为精确 reference;PyTorch BSR 只作为 baseline。 # --alg blockrow_reduce 运行仅支持 non 的 block-row tile reduction 路径;compare 对 trans/conj 保持 base。
test_spmm.py - CSR SpMM(.mtx 批量、合成或 --csv):
--csv
python tests/test_spmm.py <目录或文件.mtx> python tests/test_spmm.py --synthetic # 可选:--ops non,trans,conj python tests/test_spmm.py <目录/> --csv results.csv # CSV 覆盖 float32/float64/complex64/complex128 + int32/int64 + ops # 常用选项:--dtype、--index-dtype、--ops、--dense-cols、--block-n、--block-nnz、--max-segments、--warmup、--iters、--no-cusparse # CSR SpMM 支持 op="non" (A @ B)、op="trans" (A.T @ B)、op="conj" (A.conj().T @ B)。
test_spmm_opt.py - CSR SpMM 基线与优化版 A/B 对比:
python tests/test_spmm_opt.py <目录或文件.mtx> --dense-cols 32 python tests/test_spmm_opt.py <目录/> --csv spmm_opt.csv # 可选:--dtype float32|float64、--dense-cols # 常用选项:--dtype、--dense-cols、--warmup、--iters
test_spmm_coo.py - 原生 COO SpMM:
python tests/test_spmm_coo.py <目录或文件.mtx> python tests/test_spmm_coo.py --synthetic # 可选:--op non|trans|conj|all、--route rowrun|atomic|compare python tests/test_spmm_coo.py <目录/> --csv out.csv # 仅支持 --route rowrun 或 atomic(compare 不能配 --csv);可选:--op all # 与 CSR SpMM 类似的调参:--op、--dense-cols、--block-n、--block-nnz、--warmup、--iters、--no-cusparse
test_sddmm.py - CSR SDDMM(.mtx 批量或 --csv):
python tests/test_sddmm.py <目录或文件.mtx> --k 64 python tests/test_sddmm.py <目录/> --csv out.csv # 可选:--dtype float32|float64、--acc_mode f32|f64、--k 64 # 常用选项:--dtype、--index-dtype、--acc_mode、--k、--alpha、--beta、--warmup、--iters、--no-cupy-ref、--skip-api-checks
test_spgemm.py - CSR SpGEMM(.mtx 批量或 --csv):
python tests/test_spgemm.py <目录或文件.mtx> --input-mode auto python tests/test_spgemm.py <目录/> --csv results.csv # 可选:--dtype float32|float64、--input-mode auto|a_equals_b|a_at、--compare-device cpu|gpu # 常用选项:--dtype、--index-dtype、--warmup、--iters、--input-mode、--adaptive-loops、--no-cusparse、--ref-blocked-retry、--ref-isolated-retry、--ref-block-rows、--compare-device、--run-api-checks
test_spsv.py - SpSV(三角求解;仅方阵)。CSR 与 COO 共用本脚本;不存在 test_spsv_coo.py。
test_spsv_coo.py
test_spsv_sell.py - 下三角、UNIT/NON_UNIT、实数/复数、原生列主序 SELL SpSV, 支持 NON/TRANS/CONJ 操作模式。CSV 和终端字段 遵循 CSR SpSV 输出;FlagSparse_ms 和 cuSPARSE_ms 都覆盖每次调用的准备/ 分析加求解,静态 descriptor 与 SELL 转换不计时。直接 flagsparse_spsv_sell API 默认使用 ALG1;使用 --alg_num 2 或显式 flagsparse_spsv_analysis_sell + flagsparse_spsv_solve_sell 生命周期可启用 slice-cooperative ALG2 路径。TRANS/CONJ 使用专用反向依赖 kernel,且不接受 --alg_num 或 --alg2-workers。
FlagSparse_ms
cuSPARSE_ms
flagsparse_spsv_sell
--alg_num 2
flagsparse_spsv_analysis_sell
flagsparse_spsv_solve_sell
--alg_num
--alg2-workers
python tests/test_spsv.py --synthetic python tests/test_spsv.py <目录/> --csv-csr spsv.csv python tests/test_spsv.py <目录/> --csv-coo out.csv # 列与 CSR 相同 pytest -q -s tests/test_spsv_sell.py python tests/test_spsv_sell.py <目录或文件.mtx> --csv sell_alg1.csv --slice-size 32 --alg_num 1 python tests/test_spsv_sell.py <目录或文件.mtx> --csv sell_alg2.csv --slice-size 32 --alg_num 2 python tests/test_spsv_sell.py <目录或文件.mtx> --csv sell_unit.csv --unit-diagonal python tests/test_spsv_sell.py --csv sell_trans.csv --dtype float32 --slice-size 32 --ops TRANS <目录或文件.mtx> python tests/test_spsv_sell.py --csv sell_conj.csv --dtype complex64 --slice-size 32 --ops CONJ <目录或文件.mtx> python tests/test_spsv_sell.py <目录或文件.mtx> --csv sell_complex.csv --dtype complex # 可选 ALG2 调优:追加 --alg2-workers 32|64|128|256|512
test_spsm.py - SpSM(三角矩阵-稠密矩阵求解;仅方阵):
python tests/test_spsm.py --synthetic --n 512 --rhs 1024 python tests/test_spsm.py <目录/> --csv-csr spsm_csr.csv --rhs 1024 python tests/test_spsm.py <目录/> --csv-coo spsm_coo.csv --rhs 1024
test_gather.py / test_scatter.py - gather/scatter 基准(pytest 或 python tests/test_gather.py)。
python tests/test_gather.py
精度测试应使用 tests/pytest/accuracy_utils.py 中的统一断言和容差策略。计算类型算子以 CPU-FP64 作为 Golden Reference,并在断言前转换为被测 dtype;精确/逻辑类输出以 CPU int32 结果作为判等基准。
tests/pytest/accuracy_utils.py
.github/workflows/ci.yml
--help
.github/workflows/nightly-cpu.yml
.github/workflows/release.yml
v*
.github/workflows/triton-smoke.yml
.github/workflows/gpu-ci.yml
self-hosted
linux
gpu
.github/workflows/gpu-benchmark.yml
make ci
make check
make format-check
make lint
make lint-src
make release-check
make release
make gpu-env-check
tools/ci/check_gpu_environment.py
make gpu-benchmark
python tools/ci/run_gpu_benchmark.py --suite full --matrix-dir tests/data
spgemm
sddmm
CI / Build and smoke test
benchmark/performance_utils.py
latency_base
latency
speedup
benchmark/attri_util.py
benchmark/core_shapes.yaml
benchmark/summary_for_plot.py
benchmark/test_sparse_perf.py
tests/data/*.mtx
本项目采用 Apache (Version 2.0) license 许可证授权。
版权所有:中国计算机学会技术支持:开源发展技术委员会 京ICP备13000930号-9 京公网安备 11010802047560号
FlagSparse
GPU 稀疏运算库(SpMV、SpMM、SpGEMM、SDDMM、gather、scatter、多种稀疏格式)。
安装
离线时可加
--no-build-isolation避免拉取构建依赖。运行时依赖(按需安装):
复现交付测试(20 个变体 × 10 个矩阵)
交付物就是这一轮跑出的
summary.json:conf/operators.yaml里登记的 20 个交付变体 (delivery_variants:gather、scatter 的 f16/f32/f64/c32/c64,以及 spmv_csr、spmv_coo、spmm_csr、 spmm_coo、sddmm_csr 的 f32/f64)的精度和性能, 性能测 10 个 MatrixMarket 矩阵(conf/operators.yaml的delivery_matrices),热身 5 次、计时 20 次。--benchmark-input仍然给装有那 30 个.mtx的目录:--delivery-only会自动只保留清单里的 10 个, 不需要额外参数;目录里缺其中任何一个时(比如用tests/data做冒烟、或拷贝不全)不做过滤, 并在最开头几行打印说明。各后端用同一条命令, 下表列出各后端要改的地方,完整做法见各docs/<后端>.md的”交付复现”一节。--delivery-onlynon操作),并只保留输入目录里的 10 个交付矩阵。不加会读 18 个算子的超集,并跑完整的 int64/trans/conj 组合--mode normalquick每类 shape 只留一个,少跑约四成用例,还恰好跳过两个历史上出过问题的用例--timeout 36000表示内核挂住就永远等下去timeout -s KILLpip install cupy-cuda12x)pip install hip-pythonFLAGSPARSE_BACKEND=metax FLAGSPARSE_MACA_VENDOR=torch--op-benchmark-args='sddmm_csr=--no-cusparse';SDDMM 的 K sweep 要--timeout 4500FLAGSPARSE_BACKEND=mthreadsrun_flagsparse_split_delivery.py(性能取自 C API)set_env.sh;FLAGSPARSE_BACKEND=ascend FLAGSPARSE_ASCEND_VENDOR=torch--gpus 6,7spmv_coo、spmm_coo只做能力探测)FLAGSPARSE_BACKEND=xpu FLAGTREE_BACKEND=xpu TRITON_BACKEND=xpuFLAGSPARSE_BACKEND=iluvatar FLAGSPARSE_ILUVATAR_VENDOR=cupy_cusparse86a09cd(2026-09-18)之前跑出的结果不能拿来比较:旧版把 int64、trans/conj 的行也平均进了..._int_non变体,还把没有加速比的行当作 0。请用当前 runner 重跑,见prompt.md第 2 节。summary.json里各状态的含义:Passed/Failed为实测结果;Timeout表示算子跑了但触发了--timeout;NotFound表示没有该变体的行(没跑,或本后端没有配置);NoBaseline(C API)表示 内核跑通且精度通过,只是厂商库没有这个 dtype/算子可比。CUDA 上(RTX 5090,2026-09-17,sweep 收窄之前,当时的清单是 40 个变体)全程 79 分钟,最慢的是 SpSV 和 SpGEMM,各约 20 分钟; 这两个现在都不在 20 个变体的清单里,整份清单还没有完整计时过。精度阶段的
Skipped:有通过、无失败时,只因“能力边界”而跳过的用例不会把状态降成Skipped, 它们仍计入skipped并列在details.skipped里。目前豁免的只有两条原因 (run_flagsparse_pytest.py的EXPECTED_ACCURACY_SKIP_REASONS):外部矩阵目录未配置、legacy bucket 只支持 int32 列索引。其它原因的跳过仍记Skipped,全部用例都跳过(没有一个通过)也记Skipped。 新 CSR 算法在没有验证过 profile 的后端(MetaX、XPU)上不是靠豁免:test_spmv_csr_accuracy.py只参数化该后端有 profile 的算法(list_spmv_csr_algorithms(backend=...)),不会收集也就不会跳过, 交付行由真正跑起来的旧算法用例支撑。看一行Passed背后有多少用例,要看它的passed数, 不要只看状态。后端(已注册 8 个)
FlagSparse 按检测到的运行时对厂商参考实现与基线进行分发;Triton 内核本身在各后端保持不变。
torch.version.hip is Nonecupy-cuda12x)torch.version.hip is not Nonehip-python_detect_maca_runtime()torch—— 探测而非假定:做 bring-up 的那台 C550 没有 CuPytorch.musa可用torch.sparse能建 CSR/COO 张量但没注册 sparse matmul,MTT S5000 实测torch.npu可用torch—— ops-sparse 仍可用环境变量选回做 A/Btorch_xmlir/torch_xpu)torch_gcu可 import_detect_iluvatar_runtime()(torch 版本带+corex,或设备名);未实测torch—— 同 MetaX 的策略,未实测torch.cuda)后三个没有自己的算子内核:
backends/{xpu,gcu,iluvatar}/下只有__init__.py,走共享实现。天数和 MetaX 一样是 CUDA 兼容栈, 占用的是原来寒武纪mlu备用槽位的位置。 昆仑芯那条”插件必须可 import”不是多余的谨慎 —— 上游 PyTorch 给 Intel GPU 也装了torch.xpu命名空间,只看命名空间会把一块 Intel 卡认成昆仑芯。MACA 与 CUDA 源码兼容,机器上
torch.version.cuda有值而torch.version.hip为None, 靠 ROCm 那套判据分不出 MetaX 和 NVIDIA。检测按顺序尝试:FLAGSPARSE_BACKEND环境变量、 MetaX 专有的torch.version属性、MACA SDK 环境变量(MACA_PATH/MACA_HOME)、 设备名(先认厂商串,再认c550/c500型号串)。 在真机上先显式指定,等自动探测确认无误后再依赖它:调优参数按型号分档,在
spmv_csr.py的_MACA_SPMV_PROFILES和spsv.py的_MACA_SPSV_PROFILES。目前只有 C550(FlagTree metax 后端的参考型号)一档, 内容是从 CUDA 平移的;识别不出的型号会回落到它。每个参数旁注了 gfx936 上实测的 ROCm 值,是有意不继承的。在 DCU/ROCm 机器上,安装与 ROCm 版本匹配的 hip-python:
两种绑定都是可选的。若都不可用,基准测试会回退到通用的
torch.sparse参考实现, 并在*_reason/backend_status字段中给出原因,而不是直接报错。分发逻辑位于各
_*_sparse_ref_backend()辅助函数,返回("hipsparse" | "cupy_cusparse" | None, reason):flagsparse.sparse_operations._common—— SpMV CSR/COO.spmm_csr/.spmm_coo/.spgemm_csr/.gather_scatter—— 其余算子在 DCU 上跑测试
所有命令都要带
PYTHONPATH=src。开工先确认没跑到旧的已安装包 —— 这是 DCU 上最容易踩的坑:1. 先 diagnose,再跑基准。 hipSPARSE 用错时是挂住而不是报错,所以要逐级探, 不要一上来就
--op all:2. 正确性套件。
SpSV 和 SpSM 目前在 DCU 上会 GPU 内核死锁(见 docs/DCU.md 已知限制一节),需要排除掉才能跑完:
DCU 基准线:排除 851 个 SpSV/SpSM 用例后
984 passed / 1 failed,约 60 秒。 那个失败是spmv_coo/spmv_csc的容差抖动 —— 每次失败的 dtype 参数都不一样, 且单独跑就过;参数固定不变的失败才是真问题。CUDA 全量基准线:1613 passed / 3 failed。3. 策略/契约类测试 —— 不需要 GPU,秒级:
4. 逐算子基准:
看时间数据前先确认没有别的任务在争抢 GPU。
5. 统一运行器。 交付测试用复现交付测试一节的命令。 其中的
--timeout 3600保证卡住的算子不会让整轮停摆:该算子记为Timeout,然后继续往下跑。 在 DCU 上会死锁的 SpSV/SpSM 已不在交付清单里,但显式--ops spsv_csr,...仍会跑到它们; 那时--gpus 0,1单独用没有用 —— 它只是把算子分成两条队列,含 SpSV/SpSM 的那条照样要等到超时。DCU 上的完整验证流程(环境检查、旧安装包陷阱、如何确认真的走了 hipSPARSE、 已知限制、排查速查表)见 docs/DCU.md。
在 MetaX / MACA C550 上跑测试
交付测试(20 个变体)用复现交付测试一节的命令, 按表中沐曦那一行设置;确切命令见 docs/MACA.md 0.5 节。
下面这条是另一回事:连同 CSC、BSR 等其他算子一起的全量 sweep,PyTorch 基线,30 个 MatrixMarket 矩阵。由于当前内核在该平台可能卡住,暂不包含 SpSV 和 SpSM;SpMM BELL 也暂时 排除——单个矩阵的耗时可能超过其余算子之和:
--benchmark-args会追加到所有性能脚本;仅某个算子支持的参数使用可重复的--op-benchmark-args=算子名=参数。上例只向 BSR 脚本传入--resume,不会影响其他算子; 参数部分含空格时再整体引用,例如--op-benchmark-args="spmv_bsr=--dtypes float64"。 BSR 脚本会保留已完成的PASS/FAILcase、重试此前的ERRORcase, 并且只对精度为PASS的行给出bsr_speedup_vs_pytorch。结果目录包含各算子的精度、性能文件和合并汇总。后端检查、基线说明和 C550 已知限制见 docs/MACA.md。
在 MetaX 上,
test_spmm_csc.py使用 PyTorch 原生 CSC 作为性能基线:直接构造torch.sparse_csc_tensor后调用torch.sparse.mm。CSC 格式构造不计入计时,CSV 中记录为pytorch_ms,并计算triton_speedup_vs_pytorch。--no-cusparse只关闭可选的厂商基线, 不会关闭 PyTorch CSC 基线;COO 路径仍只用于精度参考。在昇腾 910B 上跑测试
只能使用 6、7 号 NPU。交付测试用复现交付测试一节的命令, 按表中昇腾那一行设置;确切命令、以 PyTorch-NPU 为基线的 5 个算子(其余只做能力探测)、 环境检查和已知限制见 docs/ASCEND.md。
目录说明
src/flagsparse/sparse_operations/下每个算子只有一份共享实现;sparse_operations/backends/<后端>/是默认为空的覆盖层,只有真正分叉的文件才会出现在里面conf/operators.yamlgather_f32_int、spmv_csr_f32_int_non…)的单一真源。Python 侧和 C API 侧都通过tools/delivery_variants.py读它run_flagsparse_pytest.pysummary.json/summary.csv/result.htmltests/pytest/tests/ci/tests/*.pybenchmark/capi/docs/docs/README.mdmodified/prompt.md测试用法
在项目根目录执行,或先
cd tests再运行脚本(.mtx 目录可用../matrix等相对路径)。算子测试 runner - 按 YAML 算子清单逐算子运行精度/性能测试:
默认情况下,
run_flagsparse_accuracy.py和run_flagsparse_performance.py从conf/operators.yaml读取算子 id,可用--stages过滤,并按--gpus把算子分配到不同 GPU。需要一个命令同时跑两个阶段时,仍可使用run_flagsparse_pytest.py --phase both。--ops和--op-list会覆盖 YAML 选择。默认全量测试会排除手工测试项alpha_spmm_alg1和spmv_coo_tocsr;需要运行时用--ops或--op-list显式指定。spsv_descriptor_api、sparse_format_constructors这类辅助接口不是算子测试项。精度阶段会启动
pytest tests/pytest -m <operator marker> --mode quick|normal --record json --output <op>/accuracy_result.json,使用合成 CUDA 数据。性能阶段会按算子启动对应的tests/test_*.pybenchmark 命令;依赖 MatrixMarket 矩阵的命令接收--benchmark-input(默认tests/data,本地矩阵目录可传matrix),CSV 输出也会规范化成 FlagGems 风格的<op>/performance_result.json。结果默认写入pytest_results_<timestamp>/,也可通过--results-dir指定。每个算子目录在对应阶段运行后包含accuracy_stdout.log、accuracy_stderr.log、accuracy_result.json、accuracy_detail.json、performance_stdout.log、performance_stderr.log、performance.csv、performance_result.json和performance_detail.json。根目录summary.json使用 FlagGems 的timestamp/env/result结构。GPU id、命令、日志、totals、pytest case 明细和规范化 benchmark 记录等 FlagSparse 扩展字段保存在summary_flat.json和各算子的*_detail.json中。summary.csv和可选summary.xlsx用于表格查看,并会自动生成可在浏览器查看的result.html。自动生成的result.html使用summary_flat.json渲染;summary.json保持为面向外部工具的精简 FlagGems 兼容汇总。直接运行 pytest 精度测试 - 面向开发调试的小规模正确性用例,可按 marker 选择:
新增或修改算子测试项时,需要同步维护算子实现/API 注册、
conf/operators.yaml注册、pytest.inimarker、精度测试、性能命令以及公开替换/导出注册。test_spmv.py - CSR SpMV(SuiteSparse
.mtx、合成数据或 CSR CSV):test_spmv_coo.py - COO SpMV(需
--synthetic或--csv-coo,不能单独批量跑 .mtx):test_spmv_opt.py - SpMV 基线 vs 优化对比(仅
float32/float64):test_spmv_bsr.py - 原生 BSR SpMV,输出按 block-grid padding:
test_spmm.py - CSR SpMM(
.mtx批量、合成或--csv):test_spmm_opt.py - CSR SpMM 基线与优化版 A/B 对比:
test_spmm_coo.py - 原生 COO SpMM:
test_sddmm.py - CSR SDDMM(
.mtx批量或--csv):test_spgemm.py - CSR SpGEMM(
.mtx批量或--csv):test_spsv.py - SpSV(三角求解;仅方阵)。CSR 与 COO 共用本脚本;不存在
test_spsv_coo.py。test_spsv_sell.py - 下三角、UNIT/NON_UNIT、实数/复数、原生列主序 SELL SpSV, 支持 NON/TRANS/CONJ 操作模式。CSV 和终端字段 遵循 CSR SpSV 输出;
FlagSparse_ms和cuSPARSE_ms都覆盖每次调用的准备/ 分析加求解,静态 descriptor 与 SELL 转换不计时。直接flagsparse_spsv_sellAPI 默认使用 ALG1;使用--alg_num 2或显式flagsparse_spsv_analysis_sell+flagsparse_spsv_solve_sell生命周期可启用 slice-cooperative ALG2 路径。TRANS/CONJ 使用专用反向依赖 kernel,且不接受--alg_num或--alg2-workers。test_spsm.py - SpSM(三角矩阵-稠密矩阵求解;仅方阵):
test_gather.py / test_scatter.py - gather/scatter 基准(pytest 或
python tests/test_gather.py)。精度测试应使用
tests/pytest/accuracy_utils.py中的统一断言和容差策略。计算类型算子以 CPU-FP64 作为 Golden Reference,并在断言前转换为被测 dtype;精确/逻辑类输出以 CPU int32 结果作为判等基准。CI/CD
.github/workflows/ci.yml是默认 CPU CI,在 GitHub-hosted runner 上执行编译检查、格式检查、静态检查、源码严重错误检查、构建、安装校验和 smoke 测试。--help和 README 命令片段。conf/operators.yaml是参考 FlagGems 风格维护的公开 FlagSparse 稀疏算子接口注册表,并作为统一测试 runner 的默认算子清单。.github/workflows/nightly-cpu.yml是 main 分支夜间 CPU 检查,复用默认 CI 流程。.github/workflows/release.yml在v*tag 上构建源码包和 wheel,校验发布产物并上传 GitHub Release。.github/workflows/triton-smoke.yml是手动触发的 Triton smoke 检查。.github/workflows/gpu-ci.yml是手动触发的 GPU 精度 smoke 检查,依赖带self-hosted、linux、gpu标签的 runner。.github/workflows/gpu-benchmark.yml是手动触发的 GPU 性能检查,依赖带self-hosted、linux、gpu标签的 runner。make ci/make check运行默认 CPU CI 流程。make format-check、make lint、make lint-src分别对应格式检查、CI 脚本静态检查和源码严重错误检查。make release-check/make release构建、校验并生成发布产物 checksum。make gpu-env-check通过tools/ci/check_gpu_environment.py在 GPU runner 上检查 CUDA 可见性。make gpu-benchmark在 CUDA 机器上运行 quick 合成性能套件。python tools/ci/run_gpu_benchmark.py --suite full --matrix-dir tests/data可运行完整 GPU benchmark 集合,其中spgemm、sddmm会使用仓库内的.mtx测试矩阵。CI / Build and smoke test设置为必需检查。性能测试
benchmark/performance_utils.py提供 pytest 风格性能测试基类,统一默认指标(latency_base、latency、speedup)、median 统计、warmup/iteration 配置、CUDA 同步、CSV 记录和两级平均加速比规则。benchmark/attri_util.py和benchmark/core_shapes.yaml集中维护默认形状和特殊形状。benchmark/summary_for_plot.py用于解析记录文件并输出两级平均加速比统计。benchmark/test_sparse_perf.py是可选 pytest 入口;真实 GPU 性能测试仍需手动或 self-hosted GPU runner 执行。tests/data/*.mtx可作为依赖矩阵输入的 GPU benchmark 默认烟测数据集。授权许可
本项目采用 Apache (Version 2.0) license 许可证授权。