Skip to content

Commit 4356851

Browse files
authored
Document configuration of sparsity pattern representations (#256)
* Update README * Update citation * Add doc page on performance * Update CHANGELOG
1 parent 9fe61f0 commit 4356851

7 files changed

Lines changed: 83 additions & 19 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
This release is only breaking for users who touched unexported internals.
66

7-
* ![BREAKING][badge-breaking] Refactor internal types ([#254]).
8-
* ![Feature][badge-feature] Select internal data structures for sparsity pattern representations via `TracerSparsityDetector` and `TracerLocalSparsityDetector` keyword arguments `gradient_pattern_type` and `hessian_pattern_type` ([#254]).
7+
* ![BREAKING][badge-breaking] Refactor internal types ([#254])
8+
* ![Feature][badge-feature] Select internal data structures for sparsity pattern representations via the `TracerSparsityDetector` and `TracerLocalSparsityDetector` keyword arguments `gradient_pattern_type` and `hessian_pattern_type`. Refer to the new doc page on "Performance" for more information. ([#254], [#256])
99
* ![Deprecation][badge-deprecation] Move DataInterpolations.jl extension out of SCT ([#255])
1010

1111
## Version `v0.6.21`
@@ -136,6 +136,7 @@ This release is only breaking for users who touched unexported internals.
136136
[badge-maintenance]: https://img.shields.io/badge/maintenance-gray.svg
137137
[badge-docs]: https://img.shields.io/badge/docs-orange.svg
138138

139+
[#256]: https://github.com/adrhill/SparseConnectivityTracer.jl/pull/256
139140
[#255]: https://github.com/adrhill/SparseConnectivityTracer.jl/pull/255
140141
[#254]: https://github.com/adrhill/SparseConnectivityTracer.jl/pull/254
141142
[#249]: https://github.com/adrhill/SparseConnectivityTracer.jl/pull/249

CITATION.cff

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,16 @@ version: 0.1.0
1212
date-released: 2024-04-22
1313
url: "https://github.com/adrhill/SparseConnectivityTracer.jl"
1414
preferred-citation:
15-
type: generic
15+
type: article
1616
authors:
1717
- family-names: "Hill"
1818
given-names: "Adrian"
1919
orcid: "https://orcid.org/0009-0009-5977-301X"
2020
- family-names: "Dalle"
2121
given-names: "Guillaume"
2222
orcid: "https://orcid.org/0000-0003-4866-1687"
23-
title: "Sparser, Better, Faster, Stronger: Efficient Automatic Differentiation for Sparse Jacobians and Hessians"
23+
title: "Sparser, Better, Faster, Stronger: Sparsity Detection for Efficient Automatic Differentiation"
24+
journal: "Transactions on Machine Learning Research"
2425
year: 2025
25-
eprint: "2501.17737"
26-
archivePrefix: "arXiv"
27-
primaryClass: "cs.LG"
28-
url: "https://arxiv.org/abs/2501.17737"
29-
doi: "10.48550/arXiv.2501.17737"
26+
issn: "2835-8856"
27+
url: "https://openreview.net/forum?id=GtXSN52nIW"

README.md

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ julia> jacobian_sparsity(layer, x, detector)
6666
⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⢿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣷⣄⎦
6767
```
6868

69+
By default, `BitSet` is used for internal sparsity pattern representations.
70+
For very large inputs, it might be more efficient to set the type to `Set{UInt}`:
71+
72+
```julia-repl
73+
julia> detector = TracerSparsityDetector(; gradient_pattern_type=Set{UInt})
74+
```
75+
6976
### Hessian
7077

7178
For scalar functions `y = f(x)`, the sparsity pattern of the Hessian of $f$ can be obtained
@@ -95,6 +102,14 @@ julia> hessian_sparsity(g, x, detector)
95102
⋅ 1 ⋅ ⋅ 1
96103
```
97104

105+
106+
By default, a dictionaries of `BitSet` are used for internal sparsity pattern representations.
107+
For very large inputs, it might be more efficient to set the type to `Dict{UInt, Set{UInt}}`:
108+
109+
```julia-repl
110+
julia> detector = TracerSparsityDetector(; hessian_pattern_type=Dict{UInt, Set{UInt}})
111+
```
112+
98113
For more detailed examples, take a look at the [documentation](https://adrianhill.de/SparseConnectivityTracer.jl/stable).
99114

100115
### Local tracing
@@ -141,14 +156,14 @@ In fact, the functions `jacobian_sparsity` and `hessian_sparsity` are re-exporte
141156
If you use SparseConnectivityTracer in your research, please cite our preprint [*Sparser, Better, Faster, Stronger: Efficient Automatic Differentiation for Sparse Jacobians and Hessians*](https://arxiv.org/abs/2501.17737):
142157

143158
```bibtex
144-
@misc{hill2025sparserbetterfasterstronger,
145-
title={Sparser, Better, Faster, Stronger: Efficient Automatic Differentiation for Sparse Jacobians and Hessians},
146-
author={Adrian Hill and Guillaume Dalle},
147-
year={2025},
148-
eprint={2501.17737},
149-
archivePrefix={arXiv},
150-
primaryClass={cs.LG},
151-
url={https://arxiv.org/abs/2501.17737},
159+
@article{hill2025sparser,
160+
title={Sparser, Better, Faster, Stronger: Sparsity Detection for Efficient Automatic Differentiation},
161+
author={Adrian Hill and Guillaume Dalle},
162+
journal={Transactions on Machine Learning Research},
163+
issn={2835-8856},
164+
year={2025},
165+
url={https://openreview.net/forum?id=GtXSN52nIW},
166+
note={}
152167
}
153168
```
154169

docs/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
[deps]
22
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
3+
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
34
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
45
DocumenterMermaid = "a078cd44-4d9c-4618-b545-3ab9d77f9177"
6+
Flux = "587475ba-b771-5e3f-ad9e-33799f191a9c"
57
NNlib = "872c559c-99b0-510c-b3b7-b6c96a88d5cd"
68
SparseConnectivityTracer = "9f842d2f-2579-4b1d-911e-f412cf18a3f5"
79

docs/make.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ makedocs(;
2525
pages = [
2626
"Getting Started" => "index.md",
2727
"User Documentation" =>
28-
["user/global_vs_local.md", "user/limitations.md", "user/api.md"],
28+
["user/global_vs_local.md", "user/performance.md", "user/limitations.md", "user/api.md"],
2929
"Developer Documentation" => [
3030
"internals/how_it_works.md",
3131
"internals/adding_overloads.md",

docs/src/user/performance.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# [Performance](@id performance)
2+
3+
## Data structures for sparsity pattern representations
4+
5+
The most efficient internal data structure for sparsity pattern representations
6+
depends on the number of inputs and the computational graph / sparsity of a given function.
7+
8+
Let's use a convolutional layer from Flux.jl as an example.
9+
By default, SCT uses `BitSet` for Jacobian sparsity detection, which is well suited for small to medium sized functions.
10+
11+
```@example Flux
12+
using SparseConnectivityTracer, Flux, BenchmarkTools
13+
14+
x = rand(28, 28, 3, 1)
15+
layer = Conv((3, 3), 3 => 2)
16+
17+
detector_bitset = TracerSparsityDetector()
18+
jacobian_sparsity(layer, x, detector_bitset)
19+
```
20+
21+
```@example Flux
22+
@benchmark jacobian_sparsity(layer, x, detector_bitset);
23+
```
24+
25+
Instead of `BitSet`, we can use any concrete subtype of `AbstractSet{<:Integer}`, for example `Set{UInt}`.
26+
To set the sparsity pattern type for Jacobian sparsity detection, we use the keyword argument `gradient_pattern_type`:
27+
28+
```@example Flux
29+
detector_set = TracerSparsityDetector(; gradient_pattern_type=Set{UInt})
30+
@benchmark jacobian_sparsity(layer, x, detector_set);
31+
```
32+
33+
While this is slower for the given input size, the performance is highly dependant on the problem.
34+
For larger inputs (e.g. of size $224 \times 224 \times 3 \times 1$), `detector_set` will outperform `detector_bitset`.
35+
Note that memory requirement will vary as well.
36+
37+
For Hessians sparsity detection, the internal sparsity pattern representation uses either concrete subtypes of
38+
`AbstractDict{I, AbstractSet{I}}` or `AbstractSet{Tuple{I, I}}`, where `I <: Integer`.
39+
By default, `Dict{Int, BitSet)` is used.
40+
To set the sparsity pattern type, use the keyword argument `hessian_pattern_type`:
41+
42+
```@example Flux
43+
detector = TracerSparsityDetector(; hessian_pattern_type=Dict{UInt, Set{UInt}})
44+
```
45+
46+
Data structures can also be set analogously for `TracerLocalSparsityDetector`.
47+
If both Jacobian and Hessian sparsity patterns are needed,
48+
`gradient_pattern_type` and `hessian_pattern_type` can be set separately.

src/adtypes_interface.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const DOC_KWARGS = """# Keyword arguments
3636
Defaults to `$DEFAULT_SET_TYPE`.
3737
- `hessian_pattern_type::Type`:
3838
Data structure used for bookkeeping of Hessian sparsity patters, used in `hessian_sparsity`.
39-
Supports concrete subtypes of `AbstractDict{I, AbstractSet{I}}` or `AbstractSet{Tuple{I, I}}}`, where `I <: Integer`.
39+
Supports concrete subtypes of `AbstractDict{I, AbstractSet{I}}` or `AbstractSet{Tuple{I, I}}`, where `I <: Integer`.
4040
Defaults to `$DEFAULT_DICT_TYPE`.
4141
- `shared_hessian_pattern::Bool`:
4242
Indicate whether second-order information in Hessian sparsity patterns **always** shares memory and whether operators are **allowed** to mutate `HessianTracers`.

0 commit comments

Comments
 (0)