Help reshaping this array more efficiently

Hey guys, so I got an array like this:

 a[1]
15300-element Array{Float32,1}:
 0.0
 0.0
 0.0
 0.0
 0.0
 0.1
 0.0
 0.0
 0.2
 0.1
 0.0
 0.0
 0.2
 ⋮
 9.6
 0.0
 4.9
 9.7
 0.0
 4.9
 9.8
 0.0
 4.9
 9.9
 0.0
 4.9

Where the first element is x1, second element is y1, third element is z1 and so forth.

And I want to reshape it into a 5100x3 Array{Float32,2}

Currently I am doing it the most “obvious” way like this:

reshape(a[1], (5100,3))
 transpose(reshape(a[1], (3,5100)))
5100×3 LinearAlgebra.Transpose{Float32,Array{Float32,2}}:
 0.0  0.0  0.0
 0.0  0.0  0.1
 0.0  0.0  0.2
 0.1  0.0  0.0
 0.2  0.0  0.0
 0.3  0.0  0.0
 0.4  0.0  0.0
 0.5  0.0  0.0
...

Which does not seem to be very efficient and gives me a very annoying datatype for my use, ie. a 5100×3 LinearAlgebra.Transpose{Float32,Array{Float32,2}}.

Does anyone know how to improve this?

Whenever I use for loops I end up allocating way too much space, but maybe I am doing it wrong.

Kind regards

I hope this helps

a = [10.; 20.; 30.; 40.; 50.; 60.; 70.; 80.; 90.]
reshape(a,(3,3))
3×3 Array{Float64,2}:
 10.0  40.0  70.0
 20.0  50.0  80.0
 30.0  60.0  90.0

reshape(a,(3,3))'
3×3 LinearAlgebra.Adjoint{Float64,Array{Float64,2}}:
 10.0  20.0  30.0
 40.0  50.0  60.0
 70.0  80.0  90.0

permutedims(reshape(a,3,3))
3×3 Array{Float64,2}:
 10.0  20.0  30.0
 40.0  50.0  60.0
 70.0  80.0  90.0

Why do you think this?

It’s a lazy transpose. If you want a matrix, use Matrix or collect. But then you may lose efficiency (depends on how and how many times you access this array, YMMV).

Thanks! permutedims ended up doing what I want, even though I am not yet entirely sure what it does.

@Tamas_Papp I think this because my personal experience has been that sometimes it is not the most obvious way which is the best… maybe I am wrong this time though.

I ended up getting it to work with permutedims, just have to read up on what it actually does and do some benchmarking.

Thanks guys

The difference is that permutedims is an O(N) operation (it allocates a new matrix). In contrast, reshape + transpose/adjoint are O(1) operations, i.e. independent of the number of entries: They (try to) create a zero-copy view on the same underlying piece of memory.

It is obvious which approach will be faster to apply.

Your existing memory layout is consistent with a 3x5000 Matrix layout, and is good for memory access patterns that access A[1, i], A[2,i], A[3,i] together (close in time). This is the same as a 5000x3 Transpose matrix layout that is optimized for operations that need AT[i,1], AT[i,2], AT[i,3].

You should not think about annoying vs unannoying matrix types, but instead about memory layout: Choose whatever fits your access pattern. Many linear algebra functions have methods for both row-major and column-major layouts.

1 Like

The non-allocating alternative is PermutedDimsArray.

1 Like

Thanks both of you!