Thanks @antoine-levitt, I wasn’t aware of the reinterpret
function. This does appear to be much faster for large arrays:
using StaticArrays
Base.Matrix(v::Vector{SVector{S, T}}) where {S, T} = reduce(hcat, v)
eltocols(v::Vector{SVector{dim, T}}) where {dim, T} =
reshape(reinterpret(Float64, v), dim, :)
eltorows(v::Vector{SVector{dim, T}}) where {dim, T} =
transpose(reshape(reinterpret(Float64, v), dim, :))
Point{dim} = SVector{dim, Float64}
x = rand(Point{3}, 1000000)
using BenchmarkTools
@benchmark m = Matrix($x)
@benchmark mT = transpose(Matrix($x))
@benchmark m = eltocols($x)
@benchmark mT = eltorows($x)
Results:
julia> @benchmark m = Matrix($x)
BenchmarkTools.Trial:
memory estimate: 22.89 MiB
allocs estimate: 2
--------------
minimum time: 10.874 ms (0.00% GC)
median time: 17.070 ms (0.00% GC)
mean time: 15.128 ms (4.16% GC)
maximum time: 53.498 ms (78.78% GC)
--------------
samples: 331
evals/sample: 1
julia> @benchmark mT = transpose(Matrix($x))
BenchmarkTools.Trial:
memory estimate: 22.89 MiB
allocs estimate: 3
--------------
minimum time: 10.695 ms (0.00% GC)
median time: 11.154 ms (0.00% GC)
mean time: 11.346 ms (2.48% GC)
maximum time: 52.555 ms (78.71% GC)
--------------
samples: 441
evals/sample: 1
julia> @benchmark m = eltocols($x)
BenchmarkTools.Trial:
memory estimate: 64 bytes
allocs estimate: 2
--------------
minimum time: 13.549 ns (0.00% GC)
median time: 15.117 ns (0.00% GC)
mean time: 17.357 ns (6.48% GC)
maximum time: 1.122 μs (97.98% GC)
--------------
samples: 10000
evals/sample: 998
julia> @benchmark mT = eltorows($x)
BenchmarkTools.Trial:
memory estimate: 80 bytes
allocs estimate: 3
--------------
minimum time: 16.939 ns (0.00% GC)
median time: 17.799 ns (0.00% GC)
mean time: 20.796 ns (8.00% GC)
maximum time: 1.255 μs (98.28% GC)
--------------
samples: 10000
evals/sample: 998
Moreover, it doesn’t create a copy so the original x
vector can be modified by changing the entries of the matrix m
.
julia> x = rand(Point{3}, 1000000)
1000000-element Array{SArray{Tuple{3},Float64,1,3},1}:
[0.4185398323656475, 0.501898669373563, 0.41183968543604865]
julia> m = eltocols(x)
3×1000000 reshape(reinterpret(Float64, ::Array{SArray{Tuple{3},Float64,1,3},1}), 3, 1000000) with eltype Float64:
0.41854 0.86096 0.762052 0.801235 … 0.293778 0.1493 0.462913
0.501899 0.964937 0.796707 0.379564 0.932526 0.0662906 0.149578
0.41184 0.790648 0.52458 0.837944 0.921923 0.477261 0.267126
julia> m[1,1] = 0
julia> x
1000000-element Array{SArray{Tuple{3},Float64,1,3},1}:
[0.0, 0.501898669373563, 0.41183968543604865]