# Operation on transpose sparse array is slow

**URL:** <https://discourse.julialang.org/t/operation-on-transpose-sparse-array-is-slow/114330>\
**Category:** Performance\
**Created:** [May 15, 2024, 11:18pm UTC](https://discourse.julialang.org/t/operation-on-transpose-sparse-array-is-slow/114330 "2024-05-15T23:18:26Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 15, 2024, 11:50pm UTC](https://discourse.julialang.org/t/operation-on-transpose-sparse-array-is-slow/114330/2 "2024-05-15T23:50:13Z")

</div>

Transposing a sparse matrix with `Y = X'` doesn’t actually copy any data, it wraps it with a special [`Adjoint` type](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/#LinearAlgebra.Adjoint) that gives a (conjugate-)transposed view of the underlying `X` matrix.

`Adjoint` views of sparse matrices have several optimized methods, e.g. `Y * vector` is fast, but not all of the optimized methods for sparse matrices are implemented for the `Adjoint` wrapper. In particular, “logical indexing” with a vector of booleans has a [fast implementation](https://github.com/JuliaSparse/SparseArrays.jl/blob/a09f90b43105229e42ac687ab4e3f6cf50deed8c/src/sparsematrix.jl#L3166-L3175) for sparse matrices, but not for `Adjoint` wrappers thereof, and in consequence the corresponding operation on `Y` falls back to the generic method for dense matrices, which is very slow because it does not exploit sparsity.

Three possible workarounds:

1. Set `Y = SparseMatrixCSC(X')` — this makes an explicit sparse-matrix copy of the `Adjoint` wrapper, which uses up some extra memory but then subsequent operations will be fast.
2. Re-organize your code so that you do your calculations directly on the un-transposed matrix `X`
3. Define the missing specialized methods for `Adjoint` wrappers of sparse matrices. (This is [“type piracy”](https://docs.julialang.org/en/v1/manual/style-guide/#Avoid-type-piracy) but may be a reasonable stopgap measure in the short run.)

For example, your code above should become fast again if we define:

```julia
using LinearAlgebra, SparseArrays
Base.getindex(A::Adjoint{<:Any,<:SparseArrays.AbstractSparseMatrixCSC}, I::AbstractVector{Bool}, J::AbstractVector{Bool}) = parent(A)[findall(J),findall(I)]'

```

If someone wants to volunteer to make a PR to [SparseArrays.jl](https://github.com/JuliaSparse/SparseArrays.jl) with this and similar enhancements, that would be great. See also [getindex is very slow for adjoints of sparse arrays · Issue #36 · JuliaSparse/SparseArrays.jl · GitHub](https://github.com/JuliaSparse/SparseArrays.jl/issues/36) and [Strange performance with Adjoint structures](https://discourse.julialang.org/t/strange-performance-with-adjoint-structures/13397)

---

_[View the full topic](https://discourse.julialang.org/t/operation-on-transpose-sparse-array-is-slow/114330)._
