Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimizations for block sparse operations #266

Closed
1 of 4 tasks
mtfishman opened this issue Apr 10, 2020 · 2 comments
Closed
1 of 4 tasks

Optimizations for block sparse operations #266

mtfishman opened this issue Apr 10, 2020 · 2 comments
Assignees
Labels
NDTensors Requires changes to the NDTensors.jl library. performance Issues related to performance
Milestone

Comments

@mtfishman
Copy link
Member

mtfishman commented Apr 10, 2020

Here is an issue listing potential improvements to block sparse tensor operations.

@mtfishman
Copy link
Member Author

I was curious about how the strategy of combining and then contracting would work right now. Here is the function for testing that:

function contract_combine(A::ITensor, B::ITensor)
  A_uniqueinds = uniqueinds(A, B)
  B_uniqueinds = uniqueinds(B, A)
  AB_commoninds = commoninds(A, B)
  CA = combiner(A_uniqueinds)
  CB = combiner(B_uniqueinds)
  CAB = combiner(AB_commoninds)
  AC = A * CA * CAB
  BC = B * CB * dag(CAB)
  CC = AC * BC
  C = CC * dag(CA) * dag(CB)
  return C
end

Running the following code:

function main()
  Nmax = 8
  for N in 1:Nmax
    println("order = ", 2 * N)
    d = 1
    i = Index(QN(0,2) => d, QN(1,2) => d)
    is = IndexSet(ntuple(n -> settags(i, "i$n"), Val(N)))
    A = randomITensor(is'..., dag(is)...)
    B = randomITensor(is'..., dag(is)...)
    println("Contract:              ", @elapsed A' * B)
    println("Combine then contract: ", @elapsed contract_combine(A', B))
    println()
  end
end

I get:

order = 2
Contract:              7.1355e-5
Combine then contract: 0.004867469

order = 4
Contract:              0.000149889
Combine then contract: 0.006314275

order = 6
Contract:              0.000469303
Combine then contract: 0.006801207

order = 8
Contract:              0.00263369
Combine then contract: 0.007549091

order = 10
Contract:              0.027489216
Combine then contract: 0.01168987

order = 12
Contract:              0.525102576
Combine then contract: 0.034727689

order = 14
Contract:              4.987328203
Combine then contract: 0.146389961

order = 16
Contract:              49.175892434
Combine then contract: 2.307021707

where "order = N" means two order-N ITensors are contracted over N/2 shared indices. You can see there is some overhead to combining, and it currently only pays off when contracting order-10 ITensors with each other. The QN combiner code is not particularly optimized right now, so I believe that could be improved a good amount. Clearly the scaling of not combining gets quite bad as the order increases (since there is an explosion in the number of nonzero blocks, I believe 2^(N-1) nonzero blocks, while after combining there are only 2 blocks).

@emstoudenmire
Copy link
Collaborator

Very interesting! Would be neat to see if later on it could become competitive even at order 6 or 4

@mtfishman mtfishman self-assigned this Oct 8, 2020
@mtfishman mtfishman added NDTensors Requires changes to the NDTensors.jl library. performance Issues related to performance labels Oct 8, 2020
@mtfishman mtfishman added this to the v0.3 milestone Oct 8, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NDTensors Requires changes to the NDTensors.jl library. performance Issues related to performance
Projects
None yet
Development

No branches or pull requests

2 participants