Metadata-Version: 2.2
Name: torch_sparse
Version: 0.6.18+triton.hygon
Summary: FlagTree Triton implementation of optimized sparse matrix operations for PyTorch
Home-page: https://github.com/rusty1s/pytorch_sparse
Download-URL: https://github.com/rusty1s/pytorch_sparse/archive/0.6.18+triton.hygon.tar.gz
Author: Matthias Fey
Author-email: matthias.fey@tu-dortmund.de
Keywords: pytorch,sparse,sparse-matrices,autograd
Classifier: Development Status :: 5 - Production/Stable
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: scipy
Requires-Dist: triton
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-cov; extra == "test"
Dynamic: author
Dynamic: author-email
Dynamic: download-url
Dynamic: home-page
Dynamic: keywords
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# torch_sparse

这是面向 FlagOS 的 `torch_sparse 0.6.18` Triton 重构版本，保留上游
`torch_sparse` 的公开导入名、Python API 和 `torch.ops.torch_sparse` schema。
加速设备上的 COO/CSR 转换、对角线处理、CSR SpMM 和随机游走使用 FlagTree
Triton kernel；CPU 路径和图采样功能使用 PyTorch/Python 实现。

文档与项目链接：

- [torch-sparse 上游项目](https://github.com/rusty1s/pytorch_sparse)
- [torch-sparse API 文档](https://github.com/rusty1s/pytorch_sparse#functions)
- [PyTorch Sparse 文档](https://pytorch.org/docs/stable/sparse.html)

## 功能概览

本库提供带 Autograd 支持的稀疏矩阵操作，稀疏结构可以使用 COO 索引或
`SparseTensor` 表示。主要功能包括：

- COO/CSR 转换：`ind2ptr`、`ptr2ind`
- 稀疏矩阵整理：`coalesce`、`transpose`、对角线插入与删除
- 稀疏-稠密矩阵乘：`spmm` 和 `SparseTensor.matmul`，支持 `sum`、`add`、
  `mean`、`min`、`max`
- 稀疏-稀疏矩阵乘：`spspmm`，当前复用 PyTorch sparse 路径
- 图操作：随机游走、邻居采样、SAINT、重标号等
- 可选 METIS 图划分：`SparseTensor.partition`

索引张量是离散数据，不参与求导；稀疏值和稠密矩阵支持 Autograd。

## 环境要求

- Python >= 3.9
- 已安装与当前 FlagOS/DCU 软件栈匹配的 PyTorch 和 Triton
- `scipy`
- 运行 benchmark 还需要 `wget`
- 可选 METIS 构建需要 C/C++ 编译器、PyTorch C++ headers 和 64 位索引的 METIS

## 默认安装

不需要 METIS 时，直接进入本目录安装。该路径不编译 C++ 扩展：

```bash
cd /path_to_dir/torch_sparse
python -m pip install -e . --no-deps --no-build-isolation
```

构建并安装纯 Python/Triton Wheel：

```bash
python -m pip wheel . --no-deps --no-build-isolation --wheel-dir dist
python -m pip install --force-reinstall --no-deps \
  dist/torch_sparse-*-py3-none-any.whl
```

验证安装：

```bash
python -c "import torch_sparse; print(torch_sparse.__version__); print(torch_sparse.__file__)"
```
首次使用新的 Triton 配置时会进行 JIT编译，因此首次调用可能较慢。

### 按硬件后端安装

源码安装或构建 wheel 时，可以通过通用环境变量 `FLAGOS_BACKEND` 选择目标硬件：

```bash
# NVIDIA（默认值；不设置变量时使用）
python -m pip install . --no-deps --no-build-isolation

# NVIDIA/GPU
FLAGOS_BACKEND=nvidia python -m pip install . --no-deps --no-build-isolation

# Hygon/DCU
FLAGOS_BACKEND=hygon python -m pip install . --no-deps --no-build-isolation

# MThreads/MUSA
FLAGOS_BACKEND=mthreads python -m pip install . --no-deps --no-build-isolation
```

开发和调试推荐使用 editable 安装：

```bash
# 以下以 Hygon 为例；请根据目标硬件替换 hygon
FLAGOS_BACKEND=hygon python -m pip install -e . --no-deps --no-build-isolation
```

构建 wheel 时使用相同的变量:

```bash
FLAGOS_BACKEND=hygon python -m pip wheel . --no-deps --no-build-isolation --wheel-dir dist
```

可选值只有 `nvidia`、`hygon` 和 `mthreads`，默认是 `nvidia`。变量只在安装/构建阶段
读取，安装完成后修改它不会动态切换后端。生成的 wheel 带有后端版本标记，例如
`0.6.18+triton.hygon`，可以直接分发和安装：

```bash
python -m pip install --force-reinstall --no-deps dist/torch_sparse-0.6.18+triton.hygon-*.whl
```

检查已安装的后端：
```bash
python -c "import torch_sparse; print(torch_sparse.__version__); print(torch_sparse.backend_name())"
```


## 可选 METIS 支持

METIS 是可选的 CPU 图划分扩展，实现 `partition` 和 `partition2`，不影响其他
Python/Triton 算子。METIS 必须使用 64 位 `idx_t`（`IDXTYPEWIDTH=64`）。安装后：

```bash
cd /path_to_dir/torch_sparse
export METIS_ROOT=/opt/metis-5.1.0-idx64
export LD_LIBRARY_PATH="$METIS_ROOT/lib:$METIS_ROOT/lib64:$LD_LIBRARY_PATH"
TORCH_SPARSE_WITH_METIS=1 \
python -m pip install --force-reinstall . --no-deps --no-build-isolation
```

`WITH_METIS=1` 也可作为兼容开关。验证：

```bash
python -c "import torch_sparse; print(torch_sparse.has_metis)"
pytest -q -rs /path_to_dir/torch_sparse/test/test_metis.py
```

图划分始终在 CPU 执行；加速器上的 `SparseTensor` 会暂时把图结构移到 CPU，完成
后再把结果移回原设备。

MT-METIS 是独立的多线程 CPU 实现，依赖 `libmtmetis` 和 `libwildriver`。当前版本
支持通过 `TORCH_SPARSE_WITH_MTMETIS=1`（兼容 `WITH_MTMETIS=1`）构建；使用
`MTMETIS_ROOT` 指定两个库的安装前缀，必要时用 `WILDRIVER_ROOT` 单独指定
WildRiver。未启用时，`mt_partition` 会报告未编译支持；该功能不在默认安装中。

```bash
export MTMETIS_ROOT=/opt/mt-metis
export LD_LIBRARY_PATH="$MTMETIS_ROOT/lib:$LD_LIBRARY_PATH"
TORCH_SPARSE_WITH_MTMETIS=1 \
python -m pip install --force-reinstall . --no-deps --no-build-isolation
```

## 基本用法

### Coalesce

```text
torch_sparse.coalesce(index, value, m, n, op="add")
    -> (torch.LongTensor, torch.Tensor)
```

`coalesce` 按行排序索引并合并重复位置。重复项使用 `op` 指定的归约操作合并。

```python
import torch
from torch_sparse import coalesce

index = torch.tensor([[1, 0, 1, 0, 2, 1],
                      [0, 1, 1, 1, 0, 0]])
value = torch.tensor([[1., 2.], [2., 3.], [3., 4.],
                      [4., 5.], [5., 6.], [6., 7.]])

index, value = coalesce(index, value, m=3, n=2)
```

结果：

```text
index = tensor([[0, 1, 1, 2],
                [1, 0, 1, 0]])
value = tensor([[6., 8.],
                [7., 9.],
                [3., 4.],
                [5., 6.]])
```

### Transpose

```text
torch_sparse.transpose(index, value, m, n, coalesced=True)
    -> (torch.LongTensor, torch.Tensor)
```

该算子交换稀疏矩阵的行列维度：

```python
from torch_sparse import transpose

out_index, out_value = transpose(index, value, 3, 2)
```

### 稀疏-稠密矩阵乘

```text
torch_sparse.spmm(index, value, m, n, matrix) -> torch.Tensor
```

```python
import torch
from torch_sparse import spmm

index = torch.tensor([[0, 0, 1, 2, 2],
                      [0, 2, 1, 0, 1]], device="cuda")
value = torch.tensor([1., 2., 4., 1., 3.], device="cuda",
                     requires_grad=True)
matrix = torch.tensor([[1., 4.], [2., 5.], [3., 6.]],
                      device="cuda", requires_grad=True)

out = spmm(index, value, 3, 3, matrix)
# tensor([[ 7., 16.],
#         [ 8., 20.],
#         [ 7., 19.]], device="cuda:0")
out.sum().backward()
```

`SparseTensor.matmul` 还支持 `sum`、`add`、`mean`、`min` 和 `max` 归约。

### 稀疏-稀疏矩阵乘

```text
torch_sparse.spspmm(indexA, valueA, indexB, valueB, m, k, n,
                    coalesced=False)
    -> (torch.LongTensor, torch.Tensor)
```

两个输入矩阵需要是 coalesced 状态。当前实现复用 `torch.sparse.mm`，其
half/bfloat16 Sparse SpSpMM 支持取决于安装的 PyTorch 和设备后端。

```python
import torch
from torch_sparse import spspmm

indexA = torch.tensor([[0, 0, 1, 2, 2], [1, 2, 0, 0, 1]])
valueA = torch.tensor([1., 2., 3., 4., 5.])
indexB = torch.tensor([[0, 2], [1, 0]])
valueB = torch.tensor([2., 4.])

indexC, valueC = spspmm(indexA, valueA, indexB, valueB, 3, 3, 2)
# indexC = tensor([[0, 1, 2], [0, 1, 1]])
# valueC = tensor([8., 6., 8.])
```

### METIS 图划分

```python
import torch
from torch_sparse import SparseTensor

row = torch.tensor([0, 0, 1, 1, 2, 2, 3, 3])
col = torch.tensor([1, 3, 0, 2, 1, 3, 0, 2])
graph = SparseTensor(row=row, col=col, sparse_sizes=(4, 4))

partitioned, partptr, perm = graph.partition(
    num_parts=2,
    recursive=False,
    weighted=False,
)
```

`partptr` 描述各分区范围，`perm` 是按 partition id 排序后的节点排列。METIS
不同版本或默认随机状态可能给出不同但同样合法的 partition 标签，因此验证时应比较
分区合法性、排列和切边质量，而不是固定标签编号。

## 正确性测试

完整测试：

```bash
cd /path_to_dir/torch_sparse
pytest -q -rs test/
```

测试结果中的 12 个 `half/bfloat16 SpSpMM` skipped 是预期的（启用 METIS 时通常总数为
12；未启用 METIS 时还会增加 METIS 用例的 skipped）：当前
`spspmm` 复用 `torch.sparse.mm`，而 PyTorch 对该稀疏-稀疏路径的这两种 dtype
在当前后端未实现；测试因此显式跳过。这不表示 Triton 的 SpMM 正确性失败，
也不影响已覆盖 dtype 的测试结果。

只测试 Triton 加速路径：

```bash
pytest -q test/test_triton.py
```

只测试可选 METIS：

```bash
pytest -q -rs test/test_metis.py
```

## 性能测试

benchmark 默认读取 `StocF-1465`、`ldoor`、`citationCiteseer` 和
`web-Stanford` 数据集；文件不存在时会自动下载。

```bash
cd /path_to_dir/torch_sparse/benchmark
python main.py
```

CPU 模式：

```bash
python main.py --device cpu
```

benchmark 结果受设备型号、图规模、稀疏分布、缓存和 Triton 首次 JIT 编译影响，
应在同一环境与参数下比较。

COO 行索引转 CSR 行指针的 benchmark：

```bash
cd /path_to_dir/torch_sparse/benchmark

# CPU 和可用的 CUDA/DCU 设备都测试
python ptr2ind.py --device both

# 只测试 CPU；缩短试跑时间
python ptr2ind.py --device cpu --duration 0.05 --warmup 0.02

# 只测试加速设备
python ptr2ind.py --device cuda
```

### 模型实际输入测例

`mattergen_mp20_sparse_batch256.npz` 来自 OneScience MatterGen 的 MP-20 cache，包含
256 个结构的 GemNet 邻接输入（`row`、`col`、`edge_batch`、`num_atoms` 等字段），
不是随机构造的形状。

`model_benchmark.py` 测量 GemNet `get_triplets` 所需的 `SparseTensor` 行查询、
triplet 过滤及 SpMM 前向/反向；默认使用 32 个结构、512 个通道、预热 10 次并迭代
50 次：

```bash
cd /path_to_dir/torch_sparse/benchmark
python model_benchmark.py --device cuda --warmup 10 --iters 50
```

可通过 `--input` 指定其他同字段的 `.npz` 快照，`--num-structures 0` 使用全部结构，
`--compare-torch` 额外测试相同图上的 PyTorch COO SpMM。
