Static matrix with size 400

Hi,

I want to write a function to generate random matrices with size 20x20. I need to use this function frequently but I don’t need to change the matrices generated by it. So the StaticArrays seem to be a good choice. But I further notice that it only works for arrays less than 100. Is there any way to overcome this?

Thanks

why?

julia> SMatrix{20,20}(rand(20,20))
20×20 SMatrix{20, 20, Float64, 400} with indices SOneTo(20)×SOneTo(20):

#or

julia> @SMatrix(rand(20,20))
20×20 SMatrix{20, 20, Float64, 400} with indices SOneTo(20)×SOneTo(20):

It is true that the performance benefit degrades as matrix gets larger but you should try it for your workload to determine if it actually speeds things up or not, I think 20x20 is still maybe possible to still see a benefit

1 Like

I found it in this discussion. Large matrix crashes StaticArrays. Maybe things changed. Thanks for this check. I will try it myself

1 Like

1000x1000 is quite different from 20x20

Compile and runtime performance may be bad.

3 Likes

What do you do with the matrices later? Allocating a single (standard) Matrix at the start of the procedure and then using rand! instead of rand might be efficient too

3 Likes

Hi

I basically want to generate some haar random unitary matrices. The code I used before is like

using StaticArrays
using LinearAlgebra
using StatsBase
using Random

function rand_haar2(::Val{n}) where n
    M = @SMatrix randn(ComplexF64,n,n) 
    q = qr(M).Q
    L = cispi.(2 .* @SVector(rand(Float64,n)))
    return q*diagm(L)
end

Then I want to frequently use the function for instance u = rand_haar2(Val{4}()) if I want random unitary matrices with size 4. This worked well before. But now I want to generate random unitary matrices with size 20. This seems to be not so efficient based on the discussion in the link I posted. I am using the version without static arrays.

function rand_haar2_new(::Val{n}) where n
    M = randn(ComplexF64,n,n) 
    q = qr(M).Q
    L = cispi.(2 .* (rand(Float64,n)))
    return q*diagm(L)
end

It makes my code a little faster. But I am thinking if there can be further improvement.

In the version without StaticArrays, you don’t need the n to be known statically, i.e. enclosed in a Val. This will only slow down compilation. Moreover, you will be better off reusing the memory you create, like so:

using LinearAlgebra
using Random: rand!, randn!

function rand_haar2!(A::AbstractMatrix, M::AbstractMatrix, L::AbstractVector)
    randn!(M)
    Q = qr!(M).Q
    rand!(L)
    copyto!(A, Q)
    transpose(A) .*= cispi.(2 .* L)  # double check that this does indeed multiply the columns of `A`
    return A
end

n = 20
M = randn(ComplexF64, n, n);
L = rand(Float64, n);
A = similar(M);

rand_haar2!(A, M, L)
3 Likes