Reduce cache footprint by decoupling degeneracy-dependent data#387
Open
Reduce cache footprint by decoupling degeneracy-dependent data#387
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR refactors the internal representation of the fusion tree structure (block layout and sub-block indexing) for
TensorMap.The two main changes are:
fusiontreelist+fusiontreestructurearrays with a singleDictionaries.Dictionary, that can be efficiently used both through sequential access via the token system, as well as via hashing.Indicesfor the dictionary across spaces that share the same sectors but differ in degeneracies only.Motivation and context
Previously,
FusionBlockStructurestored block layout information using three parallel data structures:fusiontreelist: aVectorof(f₁, f₂)fusion tree pairs (the canonical order)fusiontreeindices: aDict{(f₁, f₂), Int}for O(1) lookup by keyfusiontreestructure: aVector{StridedStructure}indexed positionallyThis split was necessary to support both sequential access (iteration in canonical order) and keyed access (looking up a sub-block by fusion tree pair).
The drawback is redundancy: the tree pairs are stored twice.
Additionally, many operations require multiple indirections that are handled manually throughout the package. (
fusiontreeindices→ index →fusiontreestructure).This is precisely what
Dictionaries.jlsolves, as this is more or less exactly mapped to the internal structure of theDictionarytype.The
gettokenfunction maps keys to integers, andgettokenvaluethen simply uses that integer to index into the vector of values.This effectively replaces all three structures with a single
Dictionary{typeof(((f₁,f₂)), StridedStructure}.Additionally,
fusiontrees(t)/fusiontrees(W)— which enumerate valid fusion tree pairs — benefits from caching, but the cache key is the sector structure of the space (not its degeneracy dimensions, which affect sub-block sizes but not the set of valid trees).The
Indicestype fromDictionaries.jlserves as the keyed-ordered set of fusion tree pairs that can be shared acrossHomSpaces with identical sector structure. (the combination offusiontreelistandfusiontreeindicesfrom before)Design Decisions
fusiontreelistis cached by sector structure:fusiontreelist(W)uses a customHashedwrapper to hash/compareHomSpaces only by their sector structure (ignoring degeneracy dimensions).This solves the issue that the set of valid fusion tree pairs
(f₁, f₂)depends only on which sectors appear in each index space and their dualities — not on how many states each sector has.By caching the
fusiontreelistat this coarser level,HomSpaces that share the same sectors but differ in multiplicities can share the sameIndices.File reorganization:
tensorstructure.jlAs the
HomSpacefile was getting somewhat large, I also refactored and split off the functions that construct tensor structure into their own file, included just beforeabstracttensor.jl.This code is really about tensor data layout, not about the abstract space itself.
Questions
Dictionaries.jl-based options, to avoid the mental load of having both and the maintenance of supporting different dictionaries defined within TensorKit?