Skip to content

Commit acfa273

Browse files
lkdvosJutho
andauthored
Add benchmark suite (#233)
* Add benchmark suite * reorganize benchmarks * reorganize part II * Add `permute` benchmarks * Add tensornetwork benchmarks * Add TensorKitBenchmarks * Add BenchUtils * Add LinalgBenchmarks * Add IndexManipulationBenchmarks * Add TensorNetworkBenchmarks * Clean up * Add readme and gitignore * Update benchmark/TensorKitBenchmarks/utils/BenchUtils.jl Co-authored-by: Jutho <[email protected]> * formatter --------- Co-authored-by: Jutho <[email protected]>
1 parent fa15514 commit acfa273

File tree

87 files changed

+643
-2
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+643
-2
lines changed

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ __pycache__
77
.ipynb*
88
Manifest.toml
99
.vscode
10-
benchmark
1110
experimental
1211
refs
1312
*.mathcha
14-
13+
/benchmark/results/

benchmark/Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[deps]
2+
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
3+
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
4+
TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec"

benchmark/README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# TensorKit Benchmarks
2+
3+
This directory contains a benchmark suite for TensorKit.
4+
Most of the benchmarks are designed to capture performance characteristics of the library, and are not intended to be used as a benchmark suite for comparing different libraries.
5+
In particular, the main goal here is to catch performance regressions and/or improvements between different versions of TensorKit.
6+
7+
## Running the benchmarks
8+
9+
The benchmarks are written using `BenchmarkTools.jl`, and the full suite can be found in the `SUITE` global variable defined in `benchmarks.jl`.
10+
Sometimes, it is useful to run only a subset of the benchmarks.
11+
To do this, you can use the `--modules` flag to specify which modules to run.
12+
Alternatively, you can use the `TensorKitBenchmarks` module directly, which is designed after `BaseBenchmarks` to allow for conditional loading of the benchmarks.
13+
14+
For a more streamlined CLI experience, you can use [`AirspeedVelocity.jl`](https://github.com/MilesCranmer/AirspeedVelocity.jl) to run the benchmarks.
15+
The following command will run the benchmarks and compare with the current master branch:
16+
17+
```bash
18+
benchpkg TensorKit \
19+
--rev=dirty,master \
20+
-o benchmark/results/ \
21+
-exeflags="--threads=4"
22+
```
23+
24+
To compare with previous results, the following command can be used:
25+
26+
```bash
27+
benchpkgtable TensorKit \
28+
--rev=dirty,master \
29+
-i benchmark/results/ \
30+
-o benchmark/results/ \
31+
```
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
module TensorKitBenchmarks
2+
3+
using BenchmarkTools
4+
using TensorKit
5+
using TOML
6+
7+
BenchmarkTools.DEFAULT_PARAMETERS.seconds = 1.0
8+
BenchmarkTools.DEFAULT_PARAMETERS.samples = 10000
9+
BenchmarkTools.DEFAULT_PARAMETERS.time_tolerance = 0.15
10+
BenchmarkTools.DEFAULT_PARAMETERS.memory_tolerance = 0.01
11+
12+
const PARAMS_PATH = joinpath(@__DIR__, "etc", "params.json")
13+
const SUITE = BenchmarkGroup()
14+
const MODULES = Dict("linalg" => :LinalgBenchmarks,
15+
"indexmanipulations" => :IndexManipulationBenchmarks,
16+
"tensornetworks" => :TensorNetworkBenchmarks)
17+
18+
load!(id::AbstractString; kwargs...) = load!(SUITE, id; kwargs...)
19+
20+
function load!(group::BenchmarkGroup, id::AbstractString; tune::Bool=false)
21+
modsym = MODULES[id]
22+
modpath = joinpath(dirname(@__FILE__), id, "$(modsym).jl")
23+
Core.eval(@__MODULE__, :(include($modpath)))
24+
mod = Core.eval(@__MODULE__, modsym)
25+
modsuite = @invokelatest getglobal(mod, :SUITE)
26+
group[id] = modsuite
27+
if tune
28+
results = BenchmarkTools.load(PARAMS_PATH)[1]
29+
haskey(results, id) && loadparams!(modsuite, results[id], :evals)
30+
end
31+
return group
32+
end
33+
34+
loadall!(; kwargs...) = loadall!(SUITE; kwargs...)
35+
36+
function loadall!(group::BenchmarkGroup; verbose::Bool=true, tune::Bool=false)
37+
for id in keys(MODULES)
38+
if verbose
39+
print("loading group $(repr(id))... ")
40+
time = @elapsed load!(group, id, tune=false)
41+
println("done (took $time seconds)")
42+
else
43+
load!(group, id; tune=false)
44+
end
45+
end
46+
if tune
47+
results = BenchmarkTools.load(PARAMS_PATH)[1]
48+
for (id, suite) in group
49+
haskey(results, id) && loadparams!(suite, results[id], :evals)
50+
end
51+
end
52+
return group
53+
end
54+
55+
end
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
module IndexManipulationBenchmarks
2+
3+
include(joinpath(@__DIR__, "..", "utils", "BenchUtils.jl"))
4+
5+
using .BenchUtils
6+
using BenchmarkTools
7+
using TensorKit
8+
using TOML
9+
10+
const SUITE = BenchmarkGroup()
11+
const all_parameters = TOML.parsefile(joinpath(@__DIR__, "benchparams.toml"))
12+
13+
# permute!
14+
# --------
15+
function init_permute_tensors(T, W, p)
16+
C = randn(T, permute(W, p))
17+
A = randn(T, W)
18+
return C, A
19+
end
20+
function benchmark_permute!(benchgroup, params::Dict)
21+
haskey(benchgroup, "permute") || addgroup!(benchgroup, "permute")
22+
bench = benchgroup["permute"]
23+
for kwargs in expand_kwargs(params)
24+
benchmark_permute!(bench; kwargs...)
25+
end
26+
return nothing
27+
end
28+
function benchmark_permute!(bench; sigmas=nothing, T="Float64", I="Trivial", dims, p)
29+
T_ = parse_type(T)
30+
I_ = parse_type(I)
31+
32+
p_ = (Tuple(p[1]), Tuple(p[2]))
33+
Vs = generate_space.(I_, dims, sigmas)
34+
35+
codomain = mapreduce(Base.Fix1(getindex, Vs), , p_[1]; init=one(eltype(Vs)))
36+
domain = mapreduce(Base.Fix1(getindex, Vs), , p_[2]; init=one(eltype(Vs)))
37+
init() = init_permute_tensors(T_, codomain domain, p_)
38+
39+
bench[T, I, dims, sigmas, p] = @benchmarkable permute!(C, A, $p_) setup = ((C, A) = $init())
40+
return nothing
41+
end
42+
43+
if haskey(all_parameters, "permute")
44+
g = addgroup!(SUITE, "permute")
45+
for params in all_parameters["permute"]
46+
benchmark_permute!(g, params)
47+
end
48+
end
49+
50+
# transpose!
51+
# ----------
52+
53+
# TODO
54+
55+
end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[[permute]]
2+
T = ["Float64"]
3+
I = "Trivial"
4+
p = [[[2, 1], []]]
5+
dims = [[7264, 7264], [43408, 1216]]
6+
7+
[[permute]]
8+
T = ["Float64"]
9+
I = "Z2Irrep"
10+
p = [[[2, 1], []]]
11+
dims = [[7264, 7264], [43408, 1216]]
12+
sigmas = [[0.5, 0.5]]
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
module LinalgBenchmarks
2+
3+
include(joinpath(@__DIR__, "..", "utils", "BenchUtils.jl"))
4+
5+
using .BenchUtils
6+
using BenchmarkTools
7+
using TensorKit
8+
using TOML
9+
10+
const SUITE = BenchmarkGroup()
11+
const all_parameters = TOML.parsefile(joinpath(@__DIR__, "benchparams.toml"))
12+
13+
# mul!
14+
# ----
15+
function init_mul_tensors(T, V)
16+
A = randn(T, V[1] V[2])
17+
B = randn(T, V[2] V[3])
18+
C = randn(T, V[1] V[3])
19+
return A, B, C
20+
end
21+
22+
function benchmark_mul!(benchgroup, params::Dict)
23+
haskey(benchgroup, "mul") || addgroup!(benchgroup, "mul")
24+
bench = benchgroup["mul"]
25+
for kwargs in expand_kwargs(params)
26+
benchmark_mul!(bench; kwargs...)
27+
end
28+
return nothing
29+
end
30+
31+
function benchmark_mul!(bench; sigmas=nothing, T="Float64", I="Trivial", dims)
32+
T_ = parse_type(T)
33+
I_ = parse_type(I)
34+
35+
Vs = generate_space.(I_, dims, sigmas)
36+
init() = init_mul_tensors(T_, Vs)
37+
38+
bench[T, I, dims, sigmas] = @benchmarkable mul!(C, A, B) setup = ((A, B, C) = $init())
39+
40+
return nothing
41+
end
42+
43+
if haskey(all_parameters, "mul")
44+
g = addgroup!(SUITE, "mul")
45+
for params in all_parameters["mul"]
46+
benchmark_mul!(g, params)
47+
end
48+
end
49+
50+
# svd!
51+
# ----
52+
function init_svd_tensor(T, V)
53+
A = randn(T, V[1] V[2])
54+
return A
55+
end
56+
57+
function benchmark_svd!(benchgroup, params::Dict)
58+
haskey(benchgroup, "svd") || addgroup!(benchgroup, "svd")
59+
bench = benchgroup["svd"]
60+
for kwargs in expand_kwargs(params)
61+
benchmark_svd!(bench; kwargs...)
62+
end
63+
return nothing
64+
end
65+
function benchmark_svd!(bench; sigmas=nothing, T="Float64", I="Trivial", dims)
66+
T_ = parse_type(T)
67+
I_ = parse_type(I)
68+
Vs = generate_space.(I_, dims, sigmas)
69+
init() = init_svd_tensor(T_, Vs)
70+
bench[T, I, dims, sigmas] = @benchmarkable tsvd!(A) setup = (A = $init())
71+
return nothing
72+
end
73+
74+
if haskey(all_parameters, "svd")
75+
g = addgroup!(SUITE, "svd")
76+
for params in all_parameters["svd"]
77+
benchmark_svd!(g, params)
78+
end
79+
end
80+
81+
end
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[[mul]]
2+
T = ["Float64", "ComplexF64"]
3+
I = "Trivial"
4+
dims = [[2, 2, 2], [8, 8, 8], [32, 32, 32], [64, 64, 64], [128, 128, 128]]
5+
6+
[[mul]]
7+
T = ["Float64", "ComplexF64"]
8+
I = "Z2Irrep"
9+
dims = [[2, 2, 2], [8, 8, 8], [32, 32, 32], [64, 64, 64], [128, 128, 128]]
10+
sigmas = [[0.5, 0.5, 0.5]]
11+
12+
[[svd]]
13+
T = ["Float64", "ComplexF64"]
14+
I = "Trivial"
15+
dims = [[2, 2], [8, 8], [32, 32], [64, 64], [128, 128]]
16+
17+
[[svd]]
18+
T = ["Float64", "ComplexF64"]
19+
I = "Z2Irrep"
20+
dims = [[2, 2], [8, 8], [32, 32], [64, 64], [128, 128]]
21+
sigmas = [[0.5, 0.5]]

0 commit comments

Comments
 (0)