# How to efficiently split StaticArrays into columns?

**URL:** <https://discourse.julialang.org/t/how-to-efficiently-split-staticarrays-into-columns/92990>\
**Category:** Performance\
**Tags:** staticarrays\
**Created:** [January 15, 2023, 10:25am UTC](https://discourse.julialang.org/t/how-to-efficiently-split-staticarrays-into-columns/92990 "2023-01-15T10:25:17Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [January 15, 2023, 10:25am UTC](https://discourse.julialang.org/t/how-to-efficiently-split-staticarrays-into-columns/92990/1 "2023-01-15T10:25:17Z")

</div>

Hi!

Suppose I have:

```julia
using StaticArrays

Values = rand(SVector{3,Float64},10^6)

```

I know that I can split this into components as such:

```julia
ValuesX = getindex.(Values,1)

@benchmark getindex.($Values,1)
BenchmarkTools.Trial: 1104 samples with 1 evaluation.
 Range (min … max): 3.079 ms … 24.049 ms ┊ GC (min … max): 0.00% … 79.77%
 Time (median): 3.742 ms ┊ GC (median): 0.00%
 Time (mean ± σ): 4.519 ms ± 3.131 ms ┊ GC (mean ± σ): 14.44% ± 16.67%

  ▇▆█▇▃ ▃▃▃ ▁
  ██████████▇▁▅▄▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▅▁▁▁▄███▇ █
  3.08 ms Histogram: log(frequency) by time 17.5 ms <

```

And so on for ValuesY and ValuesZ.

How do I perform this operation more efficiently, using @views does not seem to do anything?

The reason I need it is because I have some input data given in the format/type of Values, but for the code to work on GPU I have to split it into columns.

Kind regards

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [January 15, 2023, 11:07am UTC](https://discourse.julialang.org/t/how-to-efficiently-split-staticarrays-into-columns/92990/2 "2023-01-15T11:07:47Z")

</div>

The following provides views over the different columns but I do not know anything about the GPU requirements:

```julia
view(transpose(reshape(reinterpret(Float64, Values), 3, :)), :, 1)
view(transpose(reshape(reinterpret(Float64, Values), 3, :)), :, 2)
view(transpose(reshape(reinterpret(Float64, Values), 3, :)), :, 3)

```

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [January 15, 2023, 11:48am UTC](https://discourse.julialang.org/t/how-to-efficiently-split-staticarrays-into-columns/92990/3 "2023-01-15T11:48:23Z")

</div>

> [@rafael.guerra](#):
>
> `view(transpose(reshape(reinterpret(Float64, Values), 3, :)), :, 1)`

Magnificent!

Annyoningly fast. Compared to the 3 ms I got, your approach benchmarking like this gives:

```julia
@benchmark view(transpose(reshape(reinterpret($(Float64), $(Values)), 3, :)), :, $(1))
BenchmarkTools.Trial: 10000 samples with 886 evaluations.
 Range (min … max): 127.201 ns … 40.439 μs ┊ GC (min … max): 0.00% … 99.42%
 Time (median): 135.779 ns ┊ GC (median): 0.00%
 Time (mean ± σ): 152.298 ns ± 605.257 ns ┊ GC (mean ± σ): 6.81% ± 1.72%

  ▆█▇█▅▄▃▃▂▂▂▄▄▄▃▂ ▂
  █████████████████████▇▇▇▆▆▅▄▅▅▅▅▅▄▄▃▅▅▃▄▅▆▆▆▃▅▅▄▁▁▁▁▄▃▁▄▃▃▁▃▅ █
  127 ns Histogram: log(frequency) by time 290 ns <

 Memory estimate: 80 bytes, allocs estimate: 1.

```

1 million times faster approximately? In that order of magnitude I think at least

Unfortunately I cannot get it to work on GPU and one can test that by just converting Values → CuArray(Values)

It says something about scalar indexing, but I dont understand why that happens

Kind regards

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 15, 2023, 12:12pm UTC](https://discourse.julialang.org/t/how-to-efficiently-split-staticarrays-into-columns/92990/4 "2023-01-15T12:12:54Z")

</div>

This is basically a lazy construction, so you don’t really see the performance implications before you start iterating and accessing.

Your function actually collects the data, that’s the real work,if you need it.

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [January 15, 2023, 12:15pm UTC](https://discourse.julialang.org/t/how-to-efficiently-split-staticarrays-into-columns/92990/5 "2023-01-15T12:15:33Z")

</div>

> [@rafael.guerra](#):
>
> reinterpret(Float64, Values), 3, :))

I still think it has potential though because doing:

```julia
@benchmark @CUDA.sync CuArray(view(transpose(reshape(reinterpret(eltype(eltype($ValuesCu)), Array($ValuesCu)), 3, :)), :, $(1)))
BenchmarkTools.Trial: 254 samples with 1 evaluation.
 Range (min … max): 14.121 ms … 77.067 ms ┊ GC (min … max): 0.00% … 35.87%
 Time (median): 16.216 ms ┊ GC (median): 0.00%
 Time (mean ± σ): 19.746 ms ± 8.772 ms ┊ GC (mean ± σ): 14.05% ± 18.84%

  ▃▄▅█       
  ████▇▆▄▄▅▄▅▃▃▁▁▁▂▁▁▁▁▂▁▁▁▁▁▂▁▁▂▁▂▁▂▃▄▄▃▂▃▂▃▁▃▁▁▁▁▁▁▁▁▁▁▁▂▁▃ ▃
  14.1 ms Histogram: frequency by time 49 ms <

 Memory estimate: 30.52 MiB, allocs estimate: 9.

```

Which is still 15 times faster than what I have now. This in the end becomes really slow though, because there is both “CuArray” / “Array” operations, so constantly transfer between CPU and GPU, and I have to do this 12 times per loop, so need to find out how to remove the Array i.e. need to avoid transfer to cpu

Kind regards

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [January 15, 2023, 12:27pm UTC](https://discourse.julialang.org/t/how-to-efficiently-split-staticarrays-into-columns/92990/6 "2023-01-15T12:27:11Z")

</div>

I think you can simplify it a bit, though

```julia
@view reinterpret(Float64, values)[begin:3:end] 

```

Untested.

---

<div class="post-metadata">

**Author:** ![Ahmed\_Salih](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ahmed_salih/32/206579_2.png) [@Ahmed\_Salih](https://discourse.julialang.org/u/Ahmed_Salih)\
**Post date:** [January 15, 2023, 1:35pm UTC](https://discourse.julialang.org/t/how-to-efficiently-split-staticarrays-into-columns/92990/7 "2023-01-15T13:35:47Z")

</div>

Thank you very much to you and @rafael.guerra !

Benchmarking the version you produced DNF takes ~550 ns for me on a GPU array. Really nice.

My question is though, I want this for x y z, so basically:

```julia
@view reinterpret(Float64, values)[begin+0:3:end] #x
@view reinterpret(Float64, values)[begin+1:3:end] #y
@view reinterpret(Float64, values)[begin+2:3:end] #z

```

Is this the best way to do it or is it a smarter way?

Kind regards
