README.md 9.21 KB
Newer Older
rusty1s's avatar
rusty1s committed
1
2
[pypi-image]: https://badge.fury.io/py/torch-sparse.svg
[pypi-url]: https://pypi.python.org/pypi/torch-sparse
rusty1s's avatar
rusty1s committed
3
4
5
6
[testing-image]: https://github.com/rusty1s/pytorch_sparse/actions/workflows/testing.yml/badge.svg
[testing-url]: https://github.com/rusty1s/pytorch_sparse/actions/workflows/testing.yml
[linting-image]: https://github.com/rusty1s/pytorch_sparse/actions/workflows/linting.yml/badge.svg
[linting-url]: https://github.com/rusty1s/pytorch_sparse/actions/workflows/linting.yml
rusty1s's avatar
rusty1s committed
7
8
[coverage-image]: https://codecov.io/gh/rusty1s/pytorch_sparse/branch/master/graph/badge.svg
[coverage-url]: https://codecov.io/github/rusty1s/pytorch_sparse?branch=master
rusty1s's avatar
rusty1s committed
9

rusty1s's avatar
rusty1s committed
10
# PyTorch Sparse
rusty1s's avatar
rusty1s committed
11
12

[![PyPI Version][pypi-image]][pypi-url]
rusty1s's avatar
rusty1s committed
13
14
[![Testing Status][testing-image]][testing-url]
[![Linting Status][linting-image]][linting-url]
rusty1s's avatar
rusty1s committed
15
16
17
[![Code Coverage][coverage-image]][coverage-url]

--------------------------------------------------------------------------------
rusty1s's avatar
rusty1s committed
18

rusty1s's avatar
rusty1s committed
19
This package consists of a small extension library of optimized sparse matrix operations with autograd support.
rusty1s's avatar
typos  
rusty1s committed
20
This package currently consists of the following methods:
rusty1s's avatar
rusty1s committed
21

rusty1s's avatar
rusty1s committed
22
23
24
* **[Coalesce](#coalesce)**
* **[Transpose](#transpose)**
* **[Sparse Dense Matrix Multiplication](#sparse-dense-matrix-multiplication)**
rusty1s's avatar
docs  
rusty1s committed
25
* **[Sparse Sparse Matrix Multiplication](#sparse-sparse-matrix-multiplication)**
rusty1s's avatar
rusty1s committed
26
27

All included operations work on varying data types and are implemented both for CPU and GPU.
rusty1s's avatar
rusty1s committed
28
29
To avoid the hazzle of creating [`torch.sparse_coo_tensor`](https://pytorch.org/docs/stable/torch.html?highlight=sparse_coo_tensor#torch.sparse_coo_tensor), this package defines operations on sparse tensors by simply passing `index` and `value` tensors as arguments ([with same shapes as defined in PyTorch](https://pytorch.org/docs/stable/sparse.html)).
Note that only `value` comes with autograd support, as `index` is discrete and therefore not differentiable.
rusty1s's avatar
rusty1s committed
30
31
32

## Installation

rusty1s's avatar
rusty1s committed
33
34
### Binaries

rusty1s's avatar
rusty1s committed
35
We provide pip wheels for all major OS/PyTorch/CUDA combinations, see [here](https://pytorch-geometric.com/whl).
rusty1s's avatar
rusty1s committed
36

rusty1s's avatar
rusty1s committed
37
#### PyTorch 1.9.0
rusty1s's avatar
rusty1s committed
38

rusty1s's avatar
rusty1s committed
39
To install the binaries for PyTorch 1.9.0, simply run
rusty1s's avatar
rusty1s committed
40
41

```
rusty1s's avatar
rusty1s committed
42
pip install torch-scatter torch-sparse -f https://pytorch-geometric.com/whl/torch-1.9.0+${CUDA}.html
rusty1s's avatar
rusty1s committed
43
44
```

rusty1s's avatar
rusty1s committed
45
where `${CUDA}` should be replaced by either `cpu`, `cu102`, or `cu111` depending on your PyTorch installation.
rusty1s's avatar
rusty1s committed
46

rusty1s's avatar
rusty1s committed
47
48
49
50
51
|             | `cpu` | `cu102` | `cu111` |
|-------------|-------|---------|---------|
| **Linux**   | ✅    | ✅      | ✅      |
| **Windows** | ✅    | ✅      | ✅      |
| **macOS**   | ✅    |         |         |
rusty1s's avatar
rusty1s committed
52

rusty1s's avatar
rusty1s committed
53
#### PyTorch 1.8.0/1.8.1
rusty1s's avatar
rusty1s committed
54

rusty1s's avatar
rusty1s committed
55
To install the binaries for PyTorch 1.8.0 and 1.8.1, simply run
rusty1s's avatar
rusty1s committed
56
57

```
rusty1s's avatar
rusty1s committed
58
pip install torch-scatter torch-sparse -f https://pytorch-geometric.com/whl/torch-1.8.0+${CUDA}.html
rusty1s's avatar
rusty1s committed
59
60
```

rusty1s's avatar
rusty1s committed
61
where `${CUDA}` should be replaced by either `cpu`, `cu101`, `cu102`, or `cu111` depending on your PyTorch installation.
rusty1s's avatar
rusty1s committed
62

rusty1s's avatar
rusty1s committed
63
64
65
66
67
|             | `cpu` | `cu101` | `cu102` | `cu111` |
|-------------|-------|---------|---------|---------|
| **Linux**   | ✅    | ✅      | ✅      | ✅      |
| **Windows** | ✅    | ❌      | ✅      | ✅      |
| **macOS**   | ✅    |         |         |         |
rusty1s's avatar
rusty1s committed
68

rusty1s's avatar
rusty1s committed
69
**Note:** Binaries of older versions are also provided for PyTorch 1.4.0, PyTorch 1.5.0, PyTorch 1.6.0 and PyTorch 1.7.0/1.7.1 (following the same procedure).
rusty1s's avatar
rusty1s committed
70
71
72

### From source

rusty1s's avatar
rusty1s committed
73
Ensure that at least PyTorch 1.4.0 is installed and verify that `cuda/bin` and `cuda/include` are in your `$PATH` and `$CPATH` respectively, *e.g.*:
rusty1s's avatar
rusty1s committed
74
75

```
rusty1s's avatar
rusty1s committed
76
$ python -c "import torch; print(torch.__version__)"
rusty1s's avatar
rusty1s committed
77
>>> 1.4.0
rusty1s's avatar
rusty1s committed
78

rusty1s's avatar
rusty1s committed
79
$ echo $PATH
rusty1s's avatar
rusty1s committed
80
>>> /usr/local/cuda/bin:...
rusty1s's avatar
rusty1s committed
81
82

$ echo $CPATH
rusty1s's avatar
rusty1s committed
83
>>> /usr/local/cuda/include:...
rusty1s's avatar
rusty1s committed
84
85
```

rusty1s's avatar
rusty1s committed
86
If you want to additionally build `torch-sparse` with METIS support, *e.g.* for partioning, please download and install the [METIS library](http://glaros.dtc.umn.edu/gkhome/metis/metis/download) by following the instructions in the `Install.txt` file.
rusty1s's avatar
rusty1s committed
87
Note that METIS needs to be installed with 64 bit `IDXTYPEWIDTH` by changing `include/metis.h`.
rusty1s's avatar
rusty1s committed
88
Afterwards, set the environment variable `WITH_METIS=1`.
rusty1s's avatar
rusty1s committed
89

rusty1s's avatar
rusty1s committed
90
91
92
Then run:

```
rusty1s's avatar
rusty1s committed
93
pip install torch-scatter torch-sparse
rusty1s's avatar
rusty1s committed
94
95
```

rusty1s's avatar
rusty1s committed
96
When running in a docker container without NVIDIA driver, PyTorch needs to evaluate the compute capabilities and may fail.
rusty1s's avatar
rusty1s committed
97
98
99
In this case, ensure that the compute capabilities are set via `TORCH_CUDA_ARCH_LIST`, *e.g.*:

```
rusty1s's avatar
rusty1s committed
100
export TORCH_CUDA_ARCH_LIST="6.0 6.1 7.2+PTX 7.5+PTX"
rusty1s's avatar
rusty1s committed
101
102
103
```

## Functions
rusty1s's avatar
links  
rusty1s committed
104

rusty1s's avatar
rusty1s committed
105
### Coalesce
rusty1s's avatar
rusty1s committed
106

rusty1s's avatar
docs  
rusty1s committed
107
```
rusty1s's avatar
rusty1s committed
108
torch_sparse.coalesce(index, value, m, n, op="add") -> (torch.LongTensor, torch.Tensor)
rusty1s's avatar
docs  
rusty1s committed
109
110
```

111
Row-wise sorts `index` and removes duplicate entries.
rusty1s's avatar
rusty1s committed
112
113
114
Duplicate entries are removed by scattering them together.
For scattering, any operation of [`torch_scatter`](https://github.com/rusty1s/pytorch_scatter) can be used.

rusty1s's avatar
rusty1s committed
115
#### Parameters
rusty1s's avatar
rusty1s committed
116
117
118

* **index** *(LongTensor)* - The index tensor of sparse matrix.
* **value** *(Tensor)* - The value tensor of sparse matrix.
wang-ps's avatar
wang-ps committed
119
120
* **m** *(int)* - The first dimension of sparse matrix.
* **n** *(int)* - The second dimension of sparse matrix.
rusty1s's avatar
docs  
rusty1s committed
121
* **op** *(string, optional)* - The scatter operation to use. (default: `"add"`)
rusty1s's avatar
rusty1s committed
122

rusty1s's avatar
rusty1s committed
123
#### Returns
rusty1s's avatar
rusty1s committed
124

rusty1s's avatar
docs  
rusty1s committed
125
126
* **index** *(LongTensor)* - The coalesced index tensor of sparse matrix.
* **value** *(Tensor)* - The coalesced value tensor of sparse matrix.
rusty1s's avatar
rusty1s committed
127

rusty1s's avatar
rusty1s committed
128
#### Example
rusty1s's avatar
docs  
rusty1s committed
129
130

```python
ekka's avatar
ekka committed
131
import torch
rusty1s's avatar
rusty1s committed
132
133
134
135
from torch_sparse import coalesce

index = torch.tensor([[1, 0, 1, 0, 2, 1],
                      [0, 1, 1, 1, 0, 0]])
rusty1s's avatar
rusty1s committed
136
value = torch.Tensor([[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]])
rusty1s's avatar
docs  
rusty1s committed
137

rusty1s's avatar
rusty1s committed
138
index, value = coalesce(index, value, m=3, n=2)
rusty1s's avatar
docs  
rusty1s committed
139
140
```

rusty1s's avatar
rusty1s committed
141
142
143
144
145
```
print(index)
tensor([[0, 1, 1, 2],
        [1, 0, 1, 0]])
print(value)
rusty1s's avatar
rusty1s committed
146
147
148
149
tensor([[6.0, 8.0],
        [7.0, 9.0],
        [3.0, 4.0],
        [5.0, 6.0]])
rusty1s's avatar
rusty1s committed
150
```
rusty1s's avatar
docs  
rusty1s committed
151

rusty1s's avatar
rusty1s committed
152
### Transpose
rusty1s's avatar
rusty1s committed
153

rusty1s's avatar
docs  
rusty1s committed
154
```
rusty1s's avatar
rusty1s committed
155
torch_sparse.transpose(index, value, m, n) -> (torch.LongTensor, torch.Tensor)
rusty1s's avatar
docs  
rusty1s committed
156
157
```

rusty1s's avatar
rusty1s committed
158
159
Transposes dimensions 0 and 1 of a sparse matrix.

rusty1s's avatar
rusty1s committed
160
#### Parameters
rusty1s's avatar
rusty1s committed
161
162
163

* **index** *(LongTensor)* - The index tensor of sparse matrix.
* **value** *(Tensor)* - The value tensor of sparse matrix.
wang-ps's avatar
wang-ps committed
164
165
* **m** *(int)* - The first dimension of sparse matrix.
* **n** *(int)* - The second dimension of sparse matrix.
rusty1s's avatar
typo  
rusty1s committed
166
* **coalesced** *(bool, optional)* - If set to `False`, will not coalesce the output. (default: `True`)
rusty1s's avatar
rusty1s committed
167

rusty1s's avatar
rusty1s committed
168
#### Returns
rusty1s's avatar
rusty1s committed
169

rusty1s's avatar
docs  
rusty1s committed
170
171
* **index** *(LongTensor)* - The transposed index tensor of sparse matrix.
* **value** *(Tensor)* - The transposed value tensor of sparse matrix.
rusty1s's avatar
rusty1s committed
172

rusty1s's avatar
rusty1s committed
173
#### Example
rusty1s's avatar
docs  
rusty1s committed
174
175

```python
ekka's avatar
ekka committed
176
import torch
rusty1s's avatar
rusty1s committed
177
178
179
180
from torch_sparse import transpose

index = torch.tensor([[1, 0, 1, 0, 2, 1],
                      [0, 1, 1, 1, 0, 0]])
rusty1s's avatar
rusty1s committed
181
value = torch.Tensor([[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]])
rusty1s's avatar
docs  
rusty1s committed
182

rusty1s's avatar
docs  
rusty1s committed
183
index, value = transpose(index, value, 3, 2)
rusty1s's avatar
docs  
rusty1s committed
184
185
```

rusty1s's avatar
rusty1s committed
186
187
188
189
190
```
print(index)
tensor([[0, 0, 1, 1],
        [1, 2, 0, 1]])
print(value)
rusty1s's avatar
rusty1s committed
191
192
193
194
tensor([[7.0, 9.0],
        [5.0, 6.0],
        [6.0, 8.0],
        [3.0, 4.0]])
rusty1s's avatar
rusty1s committed
195
```
rusty1s's avatar
docs  
rusty1s committed
196

rusty1s's avatar
rusty1s committed
197
### Sparse Dense Matrix Multiplication
rusty1s's avatar
rusty1s committed
198

rusty1s's avatar
docs  
rusty1s committed
199
```
200
torch_sparse.spmm(index, value, m, n, matrix) -> torch.Tensor
rusty1s's avatar
docs  
rusty1s committed
201
202
```

rusty1s's avatar
rusty1s committed
203
204
Matrix product of a sparse matrix with a dense matrix.

rusty1s's avatar
rusty1s committed
205
#### Parameters
rusty1s's avatar
docs  
rusty1s committed
206

rusty1s's avatar
rusty1s committed
207
208
* **index** *(LongTensor)* - The index tensor of sparse matrix.
* **value** *(Tensor)* - The value tensor of sparse matrix.
wang-ps's avatar
wang-ps committed
209
210
* **m** *(int)* - The first dimension of sparse matrix.
* **n** *(int)* - The second dimension of sparse matrix.
rusty1s's avatar
docs  
rusty1s committed
211
* **matrix** *(Tensor)* - The dense matrix.
rusty1s's avatar
rusty1s committed
212

rusty1s's avatar
rusty1s committed
213
#### Returns
rusty1s's avatar
rusty1s committed
214

rusty1s's avatar
docs  
rusty1s committed
215
* **out** *(Tensor)* - The dense output matrix.
rusty1s's avatar
rusty1s committed
216

rusty1s's avatar
rusty1s committed
217
#### Example
rusty1s's avatar
rusty1s committed
218
219

```python
ekka's avatar
ekka committed
220
import torch
rusty1s's avatar
rusty1s committed
221
222
223
224
from torch_sparse import spmm

index = torch.tensor([[0, 0, 1, 2, 2],
                      [0, 2, 1, 0, 1]])
rusty1s's avatar
rusty1s committed
225
226
value = torch.Tensor([1, 2, 4, 1, 3])
matrix = torch.Tensor([[1, 4], [2, 5], [3, 6]])
rusty1s's avatar
rusty1s committed
227

rusty1s's avatar
rusty1s committed
228
out = spmm(index, value, 3, 3, matrix)
rusty1s's avatar
rusty1s committed
229
230
231
232
```

```
print(out)
233
234
235
tensor([[7.0, 16.0],
        [8.0, 20.0],
        [7.0, 19.0]])
rusty1s's avatar
docs  
rusty1s committed
236
```
rusty1s's avatar
rusty1s committed
237

rusty1s's avatar
rusty1s committed
238
### Sparse Sparse Matrix Multiplication
rusty1s's avatar
rusty1s committed
239
240
241
242
243
244

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

Matrix product of two sparse tensors.
rusty1s's avatar
typo  
rusty1s committed
245
Both input sparse matrices need to be **coalesced** (use the `coalesced` attribute to force).
rusty1s's avatar
rusty1s committed
246

rusty1s's avatar
rusty1s committed
247
#### Parameters
rusty1s's avatar
rusty1s committed
248
249
250
251
252

* **indexA** *(LongTensor)* - The index tensor of first sparse matrix.
* **valueA** *(Tensor)* - The value tensor of first sparse matrix.
* **indexB** *(LongTensor)* - The index tensor of second sparse matrix.
* **valueB** *(Tensor)* - The value tensor of second sparse matrix.
wang-ps's avatar
wang-ps committed
253
254
255
* **m** *(int)* - The first dimension of first sparse matrix.
* **k** *(int)* - The second dimension of first sparse matrix and first dimension of second sparse matrix.
* **n** *(int)* - The second dimension of second sparse matrix.
rusty1s's avatar
typo  
rusty1s committed
256
* **coalesced** *(bool, optional)*: If set to `True`, will coalesce both input sparse matrices. (default: `False`)
rusty1s's avatar
rusty1s committed
257

rusty1s's avatar
rusty1s committed
258
#### Returns
rusty1s's avatar
rusty1s committed
259

rusty1s's avatar
docs  
rusty1s committed
260
261
* **index** *(LongTensor)* - The output index tensor of sparse matrix.
* **value** *(Tensor)* - The output value tensor of sparse matrix.
rusty1s's avatar
rusty1s committed
262

rusty1s's avatar
rusty1s committed
263
#### Example
rusty1s's avatar
rusty1s committed
264
265

```python
ekka's avatar
ekka committed
266
import torch
rusty1s's avatar
docs  
rusty1s committed
267
268
from torch_sparse import spspmm

rusty1s's avatar
rusty1s committed
269
indexA = torch.tensor([[0, 0, 1, 2, 2], [1, 2, 0, 0, 1]])
rusty1s's avatar
rusty1s committed
270
valueA = torch.Tensor([1, 2, 3, 4, 5])
rusty1s's avatar
rusty1s committed
271
272

indexB = torch.tensor([[0, 2], [1, 0]])
rusty1s's avatar
rusty1s committed
273
valueB = torch.Tensor([2, 4])
rusty1s's avatar
docs  
rusty1s committed
274

rusty1s's avatar
rusty1s committed
275
276
277
278
indexC, valueC = spspmm(indexA, valueA, indexB, valueB, 3, 3, 2)
```

```
ekka's avatar
ekka committed
279
print(indexC)
rusty1s's avatar
rusty1s committed
280
281
tensor([[0, 1, 2],
        [0, 1, 1]])
ekka's avatar
ekka committed
282
print(valueC)
283
tensor([8.0, 6.0, 8.0])
rusty1s's avatar
docs  
rusty1s committed
284
285
```

rusty1s's avatar
rusty1s committed
286
287
288
289
290
291
292
293
294
295
296
297
298
## C++ API

`torch-sparse` also offers a C++ API that contains C++ equivalent of python models.

```
mkdir build
cd build
# Add -DWITH_CUDA=on support for the CUDA if needed
cmake ..
make
make install
```

rusty1s's avatar
rusty1s committed
299
300
301
302
303
## Running tests

```
python setup.py test
```