Skip to content

Commit f19d7b4

Browse files
authored
docs: add sparse tensor naming and shape conventions (#90)
* remove specific cpu core alloc * docs: add naming and shape conventions guide * docs: clarify terminology and consistency in naming conventions
1 parent dbbf6e2 commit f19d7b4

4 files changed

Lines changed: 230 additions & 3 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
},
77
"runArgs": [
88
"--gpus",
9-
"all",
10-
"--cpuset-cpus",
11-
"0-1,3-5,7-23"
9+
"all"
1210
],
1311
"remoteEnv": {
1412
"SSH_AUTH_SOCK": "/tmp/ssh-agent.sock"

docs/source/contributing.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ Example test structure:
195195
Documentation
196196
-------------
197197

198+
See :doc:`naming` for the repository's conventions for sparse layouts, shapes,
199+
batching, dimensions, and specified-entry counts. Follow these conventions in
200+
new code, tests, docstrings, and pull requests.
201+
198202
Documentation is built with Sphinx. To build locally:
199203

200204
.. code-block:: bash

docs/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Sparse Multivariate Normal Distributions
6262
api/index
6363
benchmarks
6464
contributing
65+
naming
6566

6667
Installation
6768
============

docs/source/naming.rst

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
Naming and shape conventions
2+
============================
3+
4+
This guide defines the terminology used for shapes, batching, sparse layouts,
5+
and dimensions in ``torchsparsegradutils``. Use it for code, docstrings,
6+
tests, issues, and pull requests. State the logical object first and then its
7+
shape: sparse tensor terminology otherwise makes it easy to give different
8+
concepts the same name.
9+
10+
Core terminology
11+
----------------
12+
13+
Use **matrix** for a logical object with row and column axes, and use
14+
**tensor** for the PyTorch object or for a genuinely non-matrix object. For
15+
the non-hybrid matrix tensors used by most operations in this repository,
16+
the row and column axes are the final two axes. Hybrid sparse tensors may
17+
have trailing dense value dimensions.
18+
19+
* An unbatched sparse matrix has shape ``(n_rows, n_cols)``.
20+
* A batched sparse matrix (a batch of sparse matrices) has shape
21+
``(batch_size, n_rows, n_cols)``.
22+
* An unbatched square sparse matrix has shape ``(n, n)``; its batched form has
23+
shape ``(batch_size, n, n)``.
24+
* A dense matrix of right-hand sides has shape ``(n_rows, n_rhs)``; its
25+
batched form has shape ``(batch_size, n_rows, n_rhs)``.
26+
* A vector has shape ``(n,)`` and a batch of vectors has shape
27+
``(batch_size, n)``.
28+
29+
``2D``, ``3D``, ``rank 2``, and ``rank 3`` describe only the number of
30+
tensor axes. They do not identify an axis as a batch, matrix, spatial, or
31+
dense-value axis. Prefer, for example, “a batched sparse matrix with shape
32+
``(batch_size, n_rows, n_cols)``” to “a 3D sparse tensor”.
33+
34+
When an API supports at most one batch axis, say so directly. Unless an API
35+
documents an exception, batch sizes must match exactly and batch broadcasting
36+
is not supported.
37+
38+
Rank, batch, sparse, and dense dimensions
39+
------------------------------------------
40+
41+
These terms are not interchangeable:
42+
43+
* **Tensor rank** is ``tensor.ndim``, the total number of logical axes.
44+
* A **batch dimension** indexes independent problem instances. Repository
45+
convention is one leading batch axis.
46+
* A **sparse dimension** has coordinates represented by sparse indices. For
47+
COO, ``sparse_dim()`` is the number of leading indexed dimensions. CSR and
48+
CSC always have two sparse matrix dimensions.
49+
* A **dense dimension of a sparse tensor** is a trailing dimension stored in
50+
each specified value. It is not the same as a dense, ``torch.strided``
51+
tensor. Most matrix operations here require ``dense_dim() == 0`` unless
52+
documented otherwise.
53+
54+
For example, a hybrid sparse matrix with shape
55+
``(n_rows, n_cols, feature_size)`` can have two sparse dimensions and one
56+
dense feature dimension. A true three-dimensional sparse object, such as a
57+
sparse volume ``(depth, height, width)``, is different from a rank-3 tensor
58+
whose leading axis is a batch of matrices.
59+
60+
COO and compressed-layout batching
61+
----------------------------------
62+
63+
PyTorch represents batching differently for COO and compressed layouts, so
64+
documentation must preserve that distinction.
65+
66+
For COO, a tensor of shape ``(batch_size, n_rows, n_cols)`` commonly has three
67+
sparse dimensions. PyTorch does not label the first one as a batch dimension;
68+
an API in this package *logically interprets* it as one. COO batch items may
69+
have different numbers of specified entries, including zero.
70+
71+
For CSR and CSC, PyTorch represents tensors as
72+
``(*batch_shape, n_rows, n_cols, *dense_shape)``. The normal form supported by
73+
this package is ``(batch_size, n_rows, n_cols)``. Batched CSR and CSC require
74+
the same number of specified entries in every batch item; that is a storage
75+
constraint, not a mathematical requirement of batching. Do not generalise
76+
this restriction to COO.
77+
78+
Specified-element counts in batched layouts
79+
--------------------------------------------
80+
81+
``_nnz()`` is layout-specific for a batched sparse tensor. This distinction is
82+
exercised by the sparse-matrix multiplication backward tests in
83+
``torchsparsegradutils/tests/test_sparse_matmul.py``:
84+
85+
* For batched CSR, ``A.grad._nnz()`` is the number of specified entries
86+
**per batch element**.
87+
* For batched COO, ``A.grad._nnz()`` is the number of specified entries in the
88+
**whole tensor**.
89+
90+
Thus, if every batch item has ``nse_per_matrix`` specified entries and the
91+
batch size is ``batch_size``, the checked invariants are:
92+
93+
.. code-block:: python
94+
95+
# Batched CSR: PyTorch reports a per-batch-item count.
96+
assert A_csr.grad._nnz() == nse_per_matrix
97+
98+
# Batched COO: PyTorch reports a count over the complete tensor.
99+
assert A_coo.grad._nnz() == nse_per_matrix * batch_size
100+
101+
This does not make CSR's count more local mathematically; it describes the
102+
storage-count API exposed by PyTorch. For an unbatched COO or CSR matrix,
103+
``_nnz()`` is simply the count for that one matrix.
104+
105+
Specified entries, explicit zeros, and ``nnz``
106+
----------------------------------------------
107+
108+
Prefer **specified entry** and **number of specified elements** (``nse``) when
109+
the distinction matters. Sparse storage can contain an explicit value equal to
110+
zero, so “number of nonzeros” can be misleading.
111+
112+
* An **explicit zero** is a stored value equal to zero.
113+
* A **structural** or **implicit zero** is an absent coordinate interpreted as
114+
the sparse fill value.
115+
* Existing code and benchmarks may use ``nnz``. When retained, define it as
116+
the count of stored/specified entries, not necessarily mathematically
117+
nonzero values.
118+
119+
Avoid calling ``values()`` “nonzero values” unless explicit zeros are known to
120+
be absent; use “stored values” or “explicit values” instead.
121+
122+
Layout and index names
123+
----------------------
124+
125+
Use PyTorch's layout names consistently: sparse COO (``torch.sparse_coo``),
126+
sparse CSR (``torch.sparse_csr``), sparse CSC (``torch.sparse_csc``), sparse
127+
BSR (``torch.sparse_bsr``), sparse BSC (``torch.sparse_bsc``), and dense or
128+
strided (``torch.strided``). Prefer **layout** over mixing “format” and
129+
“layout” in the same API description. “Compressed sparse layout” can refer to
130+
CSR, CSC, BSR, and BSC collectively.
131+
132+
Name index arrays after the represented axis:
133+
134+
* COO: ``batch_indices``, ``row_indices``, and ``col_indices``.
135+
* CSR: ``crow_indices``, ``col_indices``, and ``values``.
136+
* CSC: ``ccol_indices``, ``row_indices``, and ``values``.
137+
138+
``crow_indices`` and ``ccol_indices`` are compressed pointers, not coordinate
139+
lists. When converting them to coordinates, say **uncompress**, **expand**, or
140+
**repeat-interleave the row/column indices**.
141+
142+
Shape symbols and operations
143+
----------------------------
144+
145+
Within a function or document, choose one scheme and keep it consistent:
146+
``batch_size`` (or ``b``), ``nrows``/``n_rows`` (or ``M``),
147+
``ncols``/``n_cols`` (or ``N``), and ``nrhs``/``n_rhs`` (or ``K``). Short local
148+
names such as ``b, nrows, ncols`` are appropriate in compact numerical code.
149+
150+
For multiplication, use:
151+
152+
.. code-block:: text
153+
154+
A: (n_rows, n_inner) or (batch_size, n_rows, n_inner)
155+
B: (n_inner, n_cols) or (batch_size, n_inner, n_cols)
156+
C: (n_rows, n_cols) or (batch_size, n_rows, n_cols)
157+
158+
For solves, use:
159+
160+
.. code-block:: text
161+
162+
A: (n, n) or (batch_size, n, n)
163+
B: (n, n_rhs) or (batch_size, n, n_rhs)
164+
X: same shape as B
165+
166+
Call ``B`` the **right-hand side**; its final axis is the number of
167+
right-hand sides, not a batch dimension. For an unbatched matrix, ``A.T``
168+
transposes the matrix axes. For a batched matrix, use ``A.mT`` or
169+
``A.transpose(-2, -1)`` to transpose the final two matrix axes while preserving
170+
the leading batch axis. Do not use ``A.T`` for batched matrices because it
171+
reverses all tensor axes.
172+
173+
Reduction, distribution, and memory wording
174+
--------------------------------------------
175+
176+
For ``A`` with shape ``(n_rows, n_cols)``, “reduce over rows” means reduce
177+
axis 0 and produce one value per column; “reduce over columns” means reduce
178+
axis 1 and produce one value per row. Avoid “row-wise” and “column-wise”
179+
unless the reduced and retained axes are both stated.
180+
181+
For ``torch.distributions``-compatible code, use
182+
``sample_shape + batch_shape + event_shape``. Sample dimensions are not batch
183+
dimensions. Spatial axes, channels, and batch axes are also distinct; use
184+
``spatial_dims``, ``spatial_shape``, ``num_channels``, and ``batch_size`` as
185+
appropriate and document a concrete volume ordering such as
186+
``(depth, height, width)``.
187+
188+
Use **view** only when storage is shared, **copy** when storage is newly
189+
allocated, and **reshape** when either may occur. “Materialise dense” means
190+
constructing a full dense tensor, for example with ``to_dense()``. Do not claim
191+
that an operation has no allocation merely because an input was expanded:
192+
``stack``, ``cat``, ``clone``, ``contiguous``, and output creation may allocate.
193+
194+
COO coalescing and validation messages
195+
--------------------------------------
196+
197+
Only COO tensors are **coalesced** or **uncoalesced**. Coalesced COO has unique,
198+
sorted coordinates; uncoalesced COO can have duplicate coordinates that sum at
199+
the same logical position. Coalesce before nonlinear operations on values
200+
unless the implementation has proved an equivalent treatment of duplicates.
201+
Do not apply this terminology to CSR or CSC.
202+
203+
Shape-validation errors should describe the accepted logical forms as well as
204+
the received shape:
205+
206+
.. code-block:: python
207+
208+
raise ValueError(
209+
"A must be an unbatched sparse matrix with shape (n_rows, n_cols) "
210+
"or a batched sparse matrix with shape (batch_size, n_rows, n_cols); "
211+
f"got shape {tuple(A.shape)}."
212+
)
213+
214+
Before submitting shape-related changes, make sure public inputs and outputs
215+
state explicit shapes; distinguish batch, matrix, spatial, channel, sample,
216+
and event axes; and separate COO-specific from compressed-layout-specific
217+
constraints.
218+
219+
References
220+
----------
221+
222+
* `PyTorch sparse tensor documentation <https://docs.pytorch.org/docs/stable/sparse.html>`_
223+
* `PyTorch distributions documentation <https://docs.pytorch.org/docs/stable/distributions.html>`_
224+
* `PyTorch tensor views documentation <https://docs.pytorch.org/docs/stable/tensor_view.html>`_

0 commit comments

Comments
 (0)