Skip to content

Commit e81492a

Browse files
authored
[ITensorMPS] Examples (#1408)
1 parent aa926d3 commit e81492a

Some content is hidden

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

62 files changed

+61
-1570
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ITensors"
22
uuid = "9136182c-28ba-11e9-034c-db9fb085ebd5"
33
authors = ["Matthew Fishman <[email protected]>", "Miles Stoudenmire <[email protected]>"]
4-
version = "0.5.1"
4+
version = "0.5.2"
55

66
[deps]
77
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"

docs/src/CodeTiming.md

Lines changed: 1 addition & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -7,93 +7,4 @@ If you are concerned about the performance of your code, a good place to start i
77

88
## Timing and benchmarking
99

10-
Julia has many nice timing tools available. Tools like [@time](https://docs.julialang.org/en/v1/base/base/#Base.@time) can be used to measure the time of specific lines of code. For microbenchmarking, we recommend the [BenchmarkTools](https://github.com/JuliaCI/BenchmarkTools.jl) package.
11-
12-
## ProfileView.jl
13-
14-
Julia has a built-in profiler in the standard module [Profile](https://docs.julialang.org/en/v1/manual/profile/). You can use it as follows:
15-
```julia
16-
julis> using ITensors
17-
18-
julia> using Profile
19-
20-
julia> @profile include(joinpath(pkgdir(ITensors), "examples", "dmrg", "1d_heisenberg_conserve_spin.jl"))
21-
After sweep 1 energy=-137.995732867390 maxlinkdim=10 maxerr=1.93E-02 time=0.862
22-
After sweep 2 energy=-138.801057557054 maxlinkdim=20 maxerr=3.37E-05 time=1.126
23-
After sweep 3 energy=-138.940075984826 maxlinkdim=91 maxerr=9.99E-11 time=1.880
24-
After sweep 4 energy=-138.940086063995 maxlinkdim=99 maxerr=1.00E-10 time=3.033
25-
After sweep 5 energy=-138.940086076330 maxlinkdim=95 maxerr=9.97E-11 time=2.824
26-
Final energy = -138.940086076330
27-
28-
julia> Profile.print()
29-
Overhead ╎ [+additional indent] Count File:Line; Function
30-
=========================================================
31-
╎6576 @Base/client.jl:485; _start()
32-
6576 @Base/client.jl:302; exec_options(opts::Base.JLOptions)
33-
6576 @Base/client.jl:372; run_main_repl(interactive::Bool, quiet::Bool, b...
34-
6576 @Base/essentials.jl:706; invokelatest
35-
6576 @Base/essentials.jl:708; #invokelatest#2
36-
6576 @Base/client.jl:387; (::Base.var"#874#876"{Bool, Bool, Bool})(REPL...
37-
╎ ╎ 6576 .../stdlib/v1.6/REPL/src/REPL.jl:305; run_repl(repl::REPL.AbstractREPL, consumer::Any)
38-
╎ ╎ 6576 ...stdlib/v1.6/REPL/src/REPL.jl:317; run_repl(repl::REPL.AbstractREPL, consumer::...
39-
[...]
40-
```
41-
We don't actually recommend printing it since the output is extremely long and difficult to read. Instead, it is best to use a visualization tool to visualize the profile, so you can see at a glance what parts of your code are taking up the most time.
42-
43-
For a quick and easy way of seeing how fast different parts of your code are, we highly recommend [ProfileView.jl](https://github.com/timholy/ProfileView.jl). All you have to do is load `ProfileView` and append a simple macro `@profview`:
44-
```julia
45-
julia> using ITensors
46-
47-
julia> using ProfileView
48-
49-
julia> @profview include(joinpath(pkgdir(ITensors), "examples", "dmrg", "1d_heisenberg_conserve_spin.jl"));
50-
After sweep 1 energy=-137.995732867390 maxlinkdim=10 maxerr=1.93E-02 time=0.977
51-
After sweep 2 energy=-138.801057557054 maxlinkdim=20 maxerr=3.37E-05 time=1.252
52-
After sweep 3 energy=-138.940075984826 maxlinkdim=91 maxerr=9.99E-11 time=2.263
53-
After sweep 4 energy=-138.940086063995 maxlinkdim=99 maxerr=1.00E-10 time=2.938
54-
After sweep 5 energy=-138.940086076330 maxlinkdim=95 maxerr=9.97E-11 time=2.988
55-
Final energy = -138.940086076330
56-
```
57-
A window will pop up with a "flame graph", where the width of a bar corresponds to the percentage of time the function call took, and as you go up in the graph you see timings for more and more nested functions. The graph will still look quite complicated for this case, but at larger bond dimensions you should see that certain functions like matrix multiplications and decompositions will start to dominate.
58-
59-
## TimerOutputs.jl
60-
61-
For more focused timing of specific parts of your code, we recommend the package [TimerOutputs](https://github.com/KristofferC/TimerOutputs.jl). This can help measure lines of code that are called repeatedly, where you want to know the accumulated time. We have some timers defined internally in ITensors.jl for the `dmrg` function which can be called as follows:
62-
```julia
63-
julia> using ITensors
64-
65-
julia> ITensors.TimerOutputs.enable_debug_timings(ITensors)
66-
timeit_debug_enabled (generic function with 1 method)
67-
68-
julia> ITensors.TimerOutputs.reset_timer!(ITensors.NDTensors.timer)
69-
──────────────────────────────────────────────────────────────────
70-
Time Allocations
71-
────────────────────── ───────────────────────
72-
Tot / % measured: 59.4μs / 0.00% 992B / 0.00%
73-
74-
Section ncalls time %tot avg alloc %tot avg
75-
──────────────────────────────────────────────────────────────────
76-
──────────────────────────────────────────────────────────────────
77-
78-
julia> include("1d_heisenberg_conserve_spin.jl")
79-
After sweep 1 energy=-137.995732867390 maxlinkdim=10 maxerr=1.93E-02 time=0.597
80-
After sweep 2 energy=-138.801057557054 maxlinkdim=20 maxerr=3.37E-05 time=0.798
81-
After sweep 3 energy=-138.940075984826 maxlinkdim=91 maxerr=9.99E-11 time=1.285
82-
After sweep 4 energy=-138.940086063995 maxlinkdim=99 maxerr=1.00E-10 time=1.878
83-
After sweep 5 energy=-138.940086076330 maxlinkdim=95 maxerr=9.97E-11 time=1.936
84-
Final energy = -138.940086076330
85-
86-
julia> ITensors.NDTensors.timer
87-
────────────────────────────────────────────────────────────────────────────────
88-
Time Allocations
89-
────────────────────── ───────────────────────
90-
Tot / % measured: 14.4s / 45.0% 9.59GiB / 95.1%
91-
92-
Section ncalls time %tot avg alloc %tot avg
93-
────────────────────────────────────────────────────────────────────────────────
94-
dmrg: eigsolve 990 4.72s 72.7% 4.76ms 7.27GiB 79.7% 7.52MiB
95-
dmrg: replacebond! 990 1.31s 20.2% 1.32ms 1.12GiB 12.2% 1.15MiB
96-
dmrg: position! 990 360ms 5.55% 364μs 571MiB 6.11% 590KiB
97-
dmrg: psi[b]*psi[b+1] 990 106ms 1.63% 107μs 182MiB 1.95% 188KiB
98-
────────────────────────────────────────────────────────────────────────────────
99-
```
10+
Julia has many nice timing tools available. Tools like [@time](https://docs.julialang.org/en/v1/base/base/#Base.@time) and [TimerOutputs](https://github.com/KristofferC/TimerOutputs.jl) can be used to measure the time of specific lines of code. For microbenchmarking, we recommend the [BenchmarkTools](https://github.com/JuliaCI/BenchmarkTools.jl) package. For profiling your code, see the Julia documentation on [profiling](https://docs.julialang.org/en/v1/manual/profile/).

docs/src/DMRGObserver.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@ for DMRG calculations such as measuring custom
66
local observables at each step and stopping DMRG
77
early if certain energy convergence conditions are met.
88

9-
In addition to the example code below, more detailed
10-
example code showing sample usage of DMRGObserver is included
11-
in the ITensor source, in the file `1d_ising_with_observer.jl`
12-
under the folder `examples/dmrg`.
13-
149
## Sample Usage
1510

1611
In the following example, we have already made a Hamiltonian MPO `H`

docs/src/Multithreading.md

Lines changed: 0 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -150,144 +150,6 @@ Threaded contract:
150150
C_contract ≈ C_threaded_contract = true
151151
```
152152

153-
Here is a full example of making use of block sparse multithreading to speed up
154-
a DMRG calculation:
155-
```julia
156-
using ITensors
157-
using LinearAlgebra
158-
using Random
159-
160-
include(joinpath(ITensors.examples_dir(), "src", "electronk.jl"))
161-
include(joinpath(ITensors.examples_dir(), "src", "hubbard.jl"))
162-
163-
function main(; Nx::Int=6, Ny::Int=3, U::Float64=4.0, t::Float64=1.0,
164-
maxdim::Int=3000, conserve_ky=true,
165-
nsweeps=10, blas_num_threads=1, strided_num_threads=1,
166-
threaded_blocksparse=true, outputlevel=1,
167-
seed=1234)
168-
Random.seed!(seed)
169-
ITensors.Strided.set_num_threads(strided_num_threads)
170-
BLAS.set_num_threads(blas_num_threads)
171-
ITensors.enable_threaded_blocksparse(threaded_blocksparse)
172-
173-
if outputlevel > 0
174-
@show Threads.nthreads()
175-
@show Sys.CPU_THREADS
176-
@show BLAS.get_num_threads()
177-
@show ITensors.Strided.get_num_threads()
178-
@show ITensors.using_threaded_blocksparse()
179-
println()
180-
end
181-
182-
N = Nx * Ny
183-
184-
maxdim = min.([100, 200, 400, 800, 2000, 3000, maxdim], maxdim)
185-
cutoff = 1E-6
186-
noise = [1E-6, 1E-7, 1E-8, 0.0]
187-
188-
sites = siteinds("ElecK", N; conserve_qns=true,
189-
conserve_ky, modulus_ky=Ny)
190-
191-
hubbard_ops = hubbard(Nx, Ny, t, U, ky=true)
192-
H = MPO(hubbard_ops, sites)
193-
194-
# Number of structural nonzero elements in a bulk
195-
# Hamiltonian MPO tensor
196-
if outputlevel > 0
197-
@show nnz(H[end÷2])
198-
@show nnzblocks(H[end÷2])
199-
end
200-
201-
# Create starting state with checkerboard
202-
# pattern
203-
state = map(CartesianIndices((Ny, Nx))) do I
204-
return iseven(I[1]) iseven(I[2]) ? "" : ""
205-
end
206-
display(state)
207-
208-
psi0 = randomMPS(sites, state; linkdims=10)
209-
210-
energy, psi = @time dmrg(H, psi0; nsweeps, maxdim, cutoff, noise, outputlevel)
211-
212-
if outputlevel > 0
213-
@show Nx, Ny
214-
@show t, U
215-
@show flux(psi)
216-
@show maxlinkdim(psi)
217-
@show energy
218-
end
219-
return nothing
220-
end
221-
222-
println("Without threaded block sparse:\n")
223-
main(; nsweeps=10, threaded_blocksparse=false)
224-
println()
225-
println("With threaded block sparse:\n")
226-
main(; nsweeps=10, threaded_blocksparse=true)
227-
println()
228-
```
229-
which when run on a laptop with 6 cores gives (after running once
230-
with 1 or 2 sweeps to trigger compilation):
231-
```
232-
Without threaded block sparse:
233-
234-
Threads.nthreads() = 5
235-
Sys.CPU_THREADS = 6
236-
BLAS.get_num_threads() = 1
237-
ITensors.Strided.get_num_threads() = 1
238-
ITensors.using_threaded_blocksparse() = false
239-
240-
splitblocks = true
241-
nnz(H[end ÷ 2]) = 67
242-
nnzblocks(H[end ÷ 2]) = 67
243-
After sweep 1 energy=-5.861157015737 maxlinkdim=78 time=0.633
244-
After sweep 2 energy=-12.397725587986 maxlinkdim=200 time=6.980
245-
After sweep 3 energy=-13.472412477115 maxlinkdim=400 time=14.257
246-
After sweep 4 energy=-13.627475223585 maxlinkdim=800 time=9.801
247-
After sweep 5 energy=-13.693628527487 maxlinkdim=2000 time=15.343
248-
After sweep 6 energy=-13.711928225391 maxlinkdim=3000 time=24.260
249-
After sweep 7 energy=-13.715575192226 maxlinkdim=3000 time=25.752
250-
After sweep 8 energy=-13.716394378223 maxlinkdim=3000 time=25.907
251-
After sweep 9 energy=-13.716535094341 maxlinkdim=3000 time=24.748
252-
After sweep 10 energy=-13.716556326664 maxlinkdim=3000 time=24.185
253-
171.903248 seconds (575.56 M allocations: 207.370 GiB, 9.37% gc time)
254-
(Nx, Ny) = (6, 3)
255-
(t, U) = (1.0, 4.0)
256-
flux(psi) = QN(("Ky",0,3),("Nf",18,-1),("Sz",0))
257-
maxlinkdim(psi) = 3000
258-
energy = -13.716556326663678
259-
260-
With threaded block sparse:
261-
262-
Threads.nthreads() = 5
263-
Sys.CPU_THREADS = 6
264-
BLAS.get_num_threads() = 1
265-
ITensors.Strided.get_num_threads() = 1
266-
ITensors.using_threaded_blocksparse() = true
267-
268-
splitblocks = true
269-
nnz(H[end ÷ 2]) = 67
270-
nnzblocks(H[end ÷ 2]) = 67
271-
After sweep 1 energy=-5.861157015735 maxlinkdim=78 time=1.117
272-
After sweep 2 energy=-12.397725588011 maxlinkdim=200 time=6.587
273-
After sweep 3 energy=-13.472412477124 maxlinkdim=400 time=12.094
274-
After sweep 4 energy=-13.627475223588 maxlinkdim=800 time=8.760
275-
After sweep 5 energy=-13.693628527488 maxlinkdim=2000 time=12.447
276-
After sweep 6 energy=-13.711928225390 maxlinkdim=3000 time=17.401
277-
After sweep 7 energy=-13.715575192226 maxlinkdim=3000 time=18.863
278-
After sweep 8 energy=-13.716394378223 maxlinkdim=3000 time=19.258
279-
After sweep 9 energy=-13.716535094341 maxlinkdim=3000 time=19.627
280-
After sweep 10 energy=-13.716556326664 maxlinkdim=3000 time=18.446
281-
134.604491 seconds (1.69 G allocations: 300.213 GiB, 18.02% gc time)
282-
(Nx, Ny) = (6, 3)
283-
(t, U) = (1.0, 4.0)
284-
flux(psi) = QN(("Ky",0,3),("Nf",18,-1),("Sz",0))
285-
maxlinkdim(psi) = 3000
286-
energy = -13.71655632666368
287-
```
288-
Speedups should be greater for problems with tensors that are more
289-
sparse or have more blocks (for example larger system sizes).
290-
291153
In addition, we plan to add more threading to other parts of the
292154
code beyond contraction (such as SVD) and improve composibility with
293155
other forms of threading like BLAS and Strided, so stay tuned!

docs/src/index.md

Lines changed: 2 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -99,57 +99,6 @@ and associated "Codebase Release" for the version you have used. The current one
9999
}
100100
```
101101

102-
## Full Example Codes
103-
104-
The ITensors.jl package contains a directory of examples, which we
105-
will continue to add to. You can find them online [here](https://github.com/ITensor/ITensors.jl/tree/main/examples).
106-
Additionally, once you have installed ITensors.jl you can find a local version
107-
of the examples in the directory `ITensors.examples_dir()`, and you can run them
108-
as follows from the Julia REPL:
109-
```julia
110-
julia> using ITensors
111-
112-
julia> cd(ITensors.examples_dir())
113-
114-
julia> readdir()
115-
7-element Array{String,1}:
116-
"basic_ops"
117-
"ctmrg"
118-
"dmrg"
119-
"gate_evolution"
120-
"krylov_methods"
121-
"src"
122-
"trg"
123-
124-
julia> cd("dmrg")
125-
126-
julia> readdir()
127-
8-element Array{String,1}:
128-
"1d_heisenberg.jl"
129-
"1d_heisenberg_conserve_spin.jl"
130-
"1d_hubbard_extended.jl"
131-
"1d_ising_with_observer.jl"
132-
"2d_heisenberg_conserve_spin.jl"
133-
"2d_hubbard_conserve_momentum.jl"
134-
"2d_hubbard_conserve_particles.jl"
135-
"input_files"
136-
137-
julia> include("1d_heisenberg.jl")
138-
After sweep 1 energy=-138.837988775764 maxlinkdim=10 time=13.760
139-
After sweep 2 energy=-138.937408365962 maxlinkdim=20 time=0.249
140-
After sweep 3 energy=-138.940084788852 maxlinkdim=100 time=1.867
141-
After sweep 4 energy=-138.940086091070 maxlinkdim=100 time=3.824
142-
After sweep 5 energy=-138.940086113999 maxlinkdim=122 time=4.527
143-
Final energy = -138.940086113999
144-
145-
julia> pwd()
146-
"[path_to_package_installation]/ITensors/examples/dmrg"
147-
```
148-
You can use your favorite text editor to view these examples. If you
149-
would like to modify them, either copy them into your own directory,
150-
or checkout ITensors.jl in development mode using the instructions
151-
in [Developing ITensors.jl](@ref).
152-
153102
## ITensor Code Samples
154103

155104
### Basic Overview
@@ -368,3 +317,5 @@ After sweep 4 energy=-138.940086009318 maxlinkdim=100 maxerr=1.05E-10 time=11.64
368317
After sweep 5 energy=-138.940086058840 maxlinkdim=96 maxerr=1.00E-10 time=12.771
369318
Final energy = -138.94008605883985
370319
```
320+
You can find more examples of running `dmrg` and related algorithms [here](https://github.com/ITensor/ITensors.jl/tree/main/src/lib/ITensorMPS/examples).
321+

examples/ITensorNetworkMaps/imps_transfer_matrix.jl

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)