# Slowdown with reinterpret

**URL:** <https://discourse.julialang.org/t/slowdown-with-reinterpret/91749>\
**Category:** Performance\
**Tags:** tuple, arrays, vector\
**Created:** [December 16, 2022, 4:28pm UTC](https://discourse.julialang.org/t/slowdown-with-reinterpret/91749 "2022-12-16T16:28:16Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![dgleich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dgleich/32/1494_2.png) [@dgleich](https://discourse.julialang.org/u/dgleich)\
**Post date:** [December 16, 2022, 4:28pm UTC](https://discourse.julialang.org/t/slowdown-with-reinterpret/91749/1 "2022-12-16T16:28:17Z")

</div>

I hope I can be forgiven for being surprised at the starkly difference between these implementations.

```julia
using BenchmarkTools
function myfunc1(n::Int)
  x = Vector{Int}(undef, 3*n)
  for i in eachindex(x)
    x[i] = i
  end 
  return x
end 

function myfunc2(n::Int)
  xdata = Vector{Tuple{Int,Int,Int}}(undef, n)
  x = reinterpret(Int, xdata)
  for i in eachindex(x)
    x[i] = i
  end 
  return xdata
end 

n = 1_000_000
@btime myfunc1($n);
@btime myfunc2($n);

```

Results

```julia
  3.068 ms (2 allocations: 22.89 MiB) # myfunc1
  16.018 ms (2 allocations: 22.89 MiB) # myfunc2 

```

Is there any way to reinterpret a vector of tuples as a linear array without such a slowdown? Is this a bug somewhere?

```julia
Julia Version 1.8.3
Commit 0434deb161e (2022-11-14 20:14 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin21.4.0)
  CPU: 16 × Intel(R) Xeon(R) W-2140B CPU @ 3.20GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-13.0.1 (ORCJIT, skylake-avx512)
  Threads: 1 on 8 virtual cores
Environment:
  JULIA_EDITOR = code
  JULIA_NUM_THREADS = 

```

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [December 16, 2022, 4:41pm UTC](https://discourse.julialang.org/t/slowdown-with-reinterpret/91749/2 "2022-12-16T16:41:57Z")

</div>

I think this slowdown might be resolved by

> <https://github.com/JuliaLang/julia/pull/44186>
>
> This PR make \`StridedReinterpretArray\`'s \`get/setindex\` pure pointer based if it…s root parent is a \`Array\`.
> Thus a "Dense" \`ReinterpretArray\` should behave more like a \`Array\`.
> Some examples with better performance:
> \`\`\`julia
> julia\> a = randn(ComplexF64, 100, 100); b = randn(100); c = a \* b;
> julia\> aa = reinterpret(Float64, a); cc = reinterpret(Float64, c);
> julia\> @btime LinearAlgebra.generic\_matvecmul!($cc, 'N', $aa, $b, LinearAlgebra.MulAddMul(true,false));
> 2.544 μs (0 allocations: 0 bytes) # on master 116.900 μs (0 allocations: 0 bytes)
> \`\`\`
> \`\`\`julia
> julia\> f(x, y) = @inbounds @simd ivdep for i in eachindex(x,y) # ivdep here is useless on master
> x\[i\] = ntoh(y\[i\])
> end
> 
> julia\> a = reinterpret(Float64, rand(UInt8, 16000));
> 
> julia\> @btime f($a, $a)
> 124.388 ns (0 allocations: 0 bytes) # on master 697.260 ns (0 allocations: 0 bytes)
> \`\`\`
> Test has been extended thus all branches should be tested.

but that PR hasn’t seen a lot of attention in a while

This package may be able to address your case:

> **[GitHub - favba/StructReinterpret.jl: StructReinterpret.jl](https://github.com/favba/StructReinterpret.jl)**
>
> StructReinterpret.jl. Contribute to favba/StructReinterpret.jl development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![Ronis\_BR](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ronis_br/32/50999_2.png) [@Ronis\_BR](https://discourse.julialang.org/u/Ronis_BR)\
**Post date:** [December 16, 2022, 4:56pm UTC](https://discourse.julialang.org/t/slowdown-with-reinterpret/91749/3 "2022-12-16T16:56:35Z")

</div>

You can cast the memory region. However, notice that this is somewhat unsafe and you will need to take care for Julia GC do not deallocate `xdata`:

```julia
function myfunc3(n::Int)
    xdata = Vector{Tuple{Int,Int,Int}}(undef, n)
    GC.@preserve xdata begin
        p = Base.unsafe_convert(Ptr{Int}, xdata)
        x = unsafe_wrap(Array, p, 3 * n)

        for i in eachindex(x)
          x[i] = i
        end
    end
    return xdata
end

```

```julia
julia> @btime myfunc1($n);
  2.484 ms (2 allocations: 22.89 MiB)

julia> @btime myfunc2($n);
  16.915 ms (2 allocations: 22.89 MiB)

julia> @btime myfunc3($n);
  2.487 ms (3 allocations: 22.89 MiB)

```

---

<div class="post-metadata">

**Author:** ![dgleich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dgleich/32/1494_2.png) [@dgleich](https://discourse.julialang.org/u/dgleich)\
**Post date:** [December 16, 2022, 7:06pm UTC](https://discourse.julialang.org/t/slowdown-with-reinterpret/91749/4 "2022-12-16T19:06:47Z")

</div>

Thanks! I was hoping to avoid the unsafe convert, but that seems like a pragmatic way to proceed. Especially with the @preserve.
