Conversation
Codecov Report❌ Patch coverage is
🚀 New features to boost your workflow:
|
Benchmark:
|
| metric (steady-state) | DefaultAllocator |
BufferAllocator |
change |
|---|---|---|---|
| wall time | 65.5 s | 50.4 s | −23% |
| GC time | 24.2 s (37%) | 10.3 s (20.5%) | −57% |
| allocated | 110.85 GiB | 39.85 GiB | −64% (−71 GiB) |
| GC pauses | ~311 | ~137 | −56% |
| full collections | 22 | 9 | −59% |
| ground-state energy | −138.940086126678 | −138.940086126678 | Δ = 0 |
Of the ~111 GiB a sweep churns through, ~71 GiB is recyclable effective-operator contraction scratch — with BufferAllocator it now comes from the reused buffer instead of the GC heap. The residual ~40 GiB (Krylov basis vectors, the gauge-step SVD, environment updates, result tensors) is not managed by the operator allocator and is therefore identical for both — that's the floor.
Raw output
model=Heisenberg S=1 L=100 χ=128 sweeps=5 krylovdim=20 reps=3
julia=1.12.6 julia_threads=1 gc_threads=1 BLAS_threads=16
DefaultAllocator | rep 1/3 | 66.79 s | GC 25.48 s ( 38.1%) | 110.85 GiB | 320 pauses | 23 full
DefaultAllocator | rep 2/3 | 65.62 s | GC 24.24 s ( 36.9%) | 110.85 GiB | 310 pauses | 22 full
DefaultAllocator | rep 3/3 | 65.41 s | GC 24.14 s ( 36.9%) | 110.85 GiB | 313 pauses | 22 full
BufferAllocator | rep 1/3 | 50.91 s | GC 10.34 s ( 20.3%) | 39.85 GiB | 135 pauses | 9 full
BufferAllocator | rep 2/3 | 50.37 s | GC 10.33 s ( 20.5%) | 39.85 GiB | 137 pauses | 9 full
BufferAllocator | rep 3/3 | 50.38 s | GC 10.32 s ( 20.5%) | 39.85 GiB | 137 pauses | 9 full
energy check: |Δ| = 0.00e+00
| # ------- | ||
| function (H::JordanMPO_AC_Hamiltonian)(x::MPSTensor) | ||
| backend, allocator = H.backend, H.allocator | ||
| y = ismissing(H.A) ? zerovector(x) : H.A(x) |
There was a problem hiding this comment.
As far as I can tell, this continuing block's action doesn't go through an @plansor with backends or allocators passed (this particular line dispatches to line 77 of mpo_derivatives.jl). I think this will occur in every algorithm which calculates a Galerkin error, as there through the projection operator * x you end up here. This isn't an issue within the actual eigsolve calls which matter in e.g. DMRG, so I'm not sure how severe this is
| In particular, this operator aims to make maximal use of the structure of the `MPOHamiltonian` to reduce the number of operations required to apply the operator to a tensor. | ||
| """ | ||
| struct JordanMPO_AC_Hamiltonian{O1, O2, O3} <: DerivativeOperator | ||
| struct JordanMPO_AC_Hamiltonian{O1, O2, O3, Bk, Al} <: DerivativeOperator |
There was a problem hiding this comment.
Genuine question, how much would compilation benefit from specifying Bk to be an AbstractBackend at this level already? And the same for the two-site version. This is done for the PrecomputedDerivative struct.
This PR threads the
backendandallocators through the DMRG implementations.As a result, we can use a single buffer that captures all temporary intermediate tensors in the effective hamiltonian applications, which is reused across sites, hopefully alleviating quite a bit of pressure from the garbage collector.
The one thing about this that is somewhat unfortunate is that this turns the algorithms into a non-threadsafe construction, and reusing the same algorithm in a parallel parameter sweep would yield wrong results.
In principle I can try to circumvent this, but I'm wondering how much that is worth it in the end?
Side note: The goal is of course to also do this for the rest of the package, but it is slightly easier to focus on a single algorithm first.