Skip to content

Incremental fixes for MPSKit#54

Open
kshyatt wants to merge 5 commits into
mainfrom
ksh/mps
Open

Incremental fixes for MPSKit#54
kshyatt wants to merge 5 commits into
mainfrom
ksh/mps

Conversation

@kshyatt
Copy link
Copy Markdown
Member

@kshyatt kshyatt commented May 7, 2026

OK, I think we do actually need the GPU-specific copyto! for things to work. We also need some explicit promotion strategies due to the extremely annoying way AbstractTensorMap storage types work 😸

@kshyatt kshyatt requested a review from lkdvos May 7, 2026 11:35
@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2026

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

kshyatt and others added 3 commits May 12, 2026 09:19
Let's try being a little more flexible with compat...
@kshyatt kshyatt force-pushed the ksh/mps branch 2 times, most recently from 1e62663 to dcb2294 Compare May 12, 2026 13:21
@assert !isnothing(I)
@views dst_dense .= src_dense[:, I]
# deal with the case where the output is not in-place
dst_dense === dst_block || copyto!(dst_block, dst_dense)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just out of curiosity, is this ever in-place?
I guess the dst_dense always comes from a similar_dense, which allocates a fresh array?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess in theory, it could be? For now I agree it's always out of place

Comment thread src/linalg/linalg.jl
Comment on lines +245 to +246
TensorKit.foreachblock(t, D) do c, (tblock, bs...)
tblock′ = lmul!(bs..., copy_dense!(similar_dense(tblock), tblock))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TensorKit.foreachblock(t, D) do c, (tblock, bs...)
tblock′ = lmul!(bs..., copy_dense!(similar_dense(tblock), tblock))
TensorKit.foreachblock(t, D) do c, (tblock, Dblock)
tblock′ = lmul!(Dblock, copy_dense!(similar_dense(tblock), tblock))

This is just because the splatting in the lmul! looks a bit strange to me since there is no non-2-arg version :)

Comment thread src/linalg/linalg.jl
Comment on lines +255 to +256
TensorKit.foreachblock(t, D) do c, (tblock, bs...)
tblock′ = rmul!(copy_dense!(similar_dense(tblock), tblock), bs...)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TensorKit.foreachblock(t, D) do c, (tblock, bs...)
tblock′ = rmul!(copy_dense!(similar_dense(tblock), tblock), bs...)
TensorKit.foreachblock(t, D) do c, (tblock, Dblock)
tblock′ = rmul!(copy_dense!(similar_dense(tblock), tblock), Dblock)

if eltype(t) === T && typeof(space(t)) === typeof(P)
return T
elseif isconcretetype(T)
elseif isconcretetype(T) || T isa Union
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! this is probably already solving a lot of issues?


# handle this separately because the storagetype of `AbstractTensorMap` is
# *always* Vector no matter the actual data storage type
TK.storagetype(t::BlockTensorMap{AbstractTensorMap{E, S, N₁, N₂}}) where {E, S, N₁, N₂} = TK.promote_storagetype(values(t.data)...)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TK.storagetype(t::BlockTensorMap{AbstractTensorMap{E, S, N₁, N₂}}) where {E, S, N₁, N₂} = TK.promote_storagetype(values(t.data)...)
TK.storagetype(t::BlockTensorMap{AbstractTensorMap{E, S, N₁, N₂}}) where {E, S, N₁, N₂} =
foldl(TK.promote_storagetype, values(t.data))

This is just to prevent the compiler from trying to overspecialize on the different amount of nonzeros.


# handle this separately because the storagetype of `AbstractTensorMap` is
# *always* Vector no matter the actual data storage type
TK.storagetype(t::SparseBlockTensorMap{AbstractTensorMap{E, S, N₁, N₂}}) where {E, S, N₁, N₂} = TK.promote_storagetype(values(t.data)...)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TK.storagetype(t::SparseBlockTensorMap{AbstractTensorMap{E, S, N₁, N₂}}) where {E, S, N₁, N₂} = TK.promote_storagetype(values(t.data)...)
TK.storagetype(t::SparseBlockTensorMap{AbstractTensorMap{E, S, N₁, N₂}}) where {E, S, N₁, N₂} =
foldl(TK.promote_storagetype, nonzero_values(t))

Note that I changed this for nonzero_values to prevent us depending on values only giving the stored ones, shouldn't matter in the end

TC′ = TK.promote_permute(TC, sectortype(S))
M = TK.promote_storagetype(TK.similarstoragetype(A, TC′), TK.similarstoragetype(B, TC′))
# explicitly compute storagetype here to work around eltype of AbstractTensorMap
MA = TK.similarstoragetype(TK.storagetype(A), TC′)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm so sorry to keep doing this, but shouldn't TK.similarstoragetype(A, TC') already give you this, and if not, maybe we should specialize TK.similarstoragetype(::BlockTensorMap, ...) instead of fixing this here?

Comment thread Project.toml
SafeTestsets = "0.1"
Strided = "2.3.3"
TensorKit = "0.16.4"
TensorKit = "0.16, 0.17"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
TensorKit = "0.16, 0.17"
TensorKit = "0.16.4"

I think the minimal bound was important, so at least it should be "0.16.4, 0.17". I would be happy to already release this in a new patch, but only if we wait for the TensorKit v0.17 release, otherwise I would merge this but wait until TensorKit releases v0.17 before tagging this. Do you have a preference about what is most convenient? I would prefer to keep the 0.16.4 for now

return KernelAbstractions.get_backend(first(BA.blocks))
end

function Base.copyto!(dest::BM, src::TA) where {T <: Number, TA <: AnyGPUMatrix{T}, BM <: BlockMatrix{T, Matrix{TA}}}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a small design question, but I would almost prefer to use Base.copy! instead of copyto!. I think that is slightly more idiomatic, since we are copying arrays and care about axes, rather than simply copying regions of memory. What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants