# Warning for array view usage?

**URL:** <https://discourse.julialang.org/t/warning-for-array-view-usage/17189>\
**Category:** Performance\
**Created:** [November 5, 2018, 10:57pm UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189 "2018-11-05T22:57:40Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)\
**Post date:** [November 5, 2018, 10:57pm UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/1 "2018-11-05T22:57:40Z")

</div>

Dear Julia experts,

I have been struggling a few hours to understand a massive slow down ( **x1000** ) of some computations. I finally spotted the problem to be caused by the use of array views in a context where one (at least myself) could think that it should cause no arm…

I join the following MWE

```julia
using BenchmarkTools

function test()
    nx=10
    ny=20
    nz=30
    nxyz=nx*ny*nz

    x1D=zeros(Float64,nxyz)
    y1D=zeros(Float64,nxyz)
    copyto!(x1D,1:nxyz)

    x3D=reshape(x1D,(nx,ny,nz))
    y3D=reshape(y1D,(ny,nz,nx))

    t=@belapsed permutedims!($y3D,$x3D,(2,3,1))
    println("time permutedims: ",t)

    x3Dv=reshape(view(x1D,1:nxyz),(nx,ny,nz))
    y3Dv=reshape(view(y1D,1:nxyz),(ny,nz,nx))
    tv=@belapsed permutedims!($y3Dv,$x3Dv,(2,3,1))
    println("time permutedims (view): ",tv)
    println(" slow down factor:",tv/t)
end

test()

```

I wonder about the opportunity to reduce the risk of this kind of mistake like a warning when views are used with linear indexing or, a different kind of view when it refers to a contiguous piece of data. What is your opinion ?

Best

---

<div class="post-metadata">

**Author:** ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)\
**Post date:** [November 5, 2018, 11:24pm UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/2 "2018-11-05T23:24:31Z")

</div>

Although your example has a one-to-one correspondence between the array index and the view index, that’s not generally the case. You’re asking `permutedims!`to calculate an index-to-index correspondence on structures whose indices are two degrees removed from the underlying data, and the inflated time reflects that. The damage could be abated by `collect(reshape(view(...)))`.

There’s a Performance Tips section on the topic: [Performance Tips · The Julia Language](https://docs.julialang.org/en/v1/manual/performance-tips/#Copying-data-is-not-always-bad-1)

---

<div class="post-metadata">

**Author:** ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)\
**Post date:** [November 5, 2018, 11:58pm UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/3 "2018-11-05T23:58:36Z")

</div>

Thanks for your explanation.  
I still wonder about the opportunity to find a way to spot (or avoid) this kind of performance issue.  
For example, using linear indexing on subarrays could emit performance warnings… Another option would be to optimize views when they actually refer to contiguous piece of array data.  
I am still a newbie in Julia and, although I appreciate very much the tools like BenchmakTools or @code\_xxx that help to eliminate performance issues, it still took me a long time to understand what was wrong in this case…

---

<div class="post-metadata">

**Author:** ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)\
**Post date:** [November 6, 2018, 2:54am UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/4 "2018-11-06T02:54:23Z")

</div>

Note that `reshape` does not copy the data; instead, it makes a new indexing structure for the same data. Similarly, transpose does not copy the data. Therefore, in a setting where `view` refers to the entire array, `reshape(view(...),...)` would be redundant and involve extra index computations; `reshape(...)` alone would probably be preferable.

---

<div class="post-metadata">

**Author:** ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)\
**Post date:** [November 6, 2018, 6:48am UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/5 "2018-11-06T06:48:32Z")

</div>

This is clear.  
What is not clear is my oversimplified MWE: in my case I wanted to permute the dims of an array slice (a contiguous slice).  
What I wanted to point out in this thread, is that my mistake of using a view in this case was difficult to find (in my larger code). The code produces the correct result but was very slow.  
I hope that other Julia (newbie) users will not loose hours debugging the same performance errors.  
Thank you again.

---

<div class="post-metadata">

**Author:** ![hckr](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hckr/32/4836_2.png) [@hckr](https://discourse.julialang.org/u/hckr)\
**Post date:** [November 6, 2018, 8:59am UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/6 "2018-11-06T08:59:01Z")

</div>

I think such things should better be handled by a linter tool for Julia. In addition, a beginner striving for high performance (who already knows usage of views) _should_ read the Performance Tips in the documentation first.

---

<div class="post-metadata">

**Author:** ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)\
**Post date:** [November 6, 2018, 9:07am UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/7 "2018-11-06T09:07:11Z")

</div>

Fair enough.  
BTW is there an efficient way to select a contiguous slice “view” on a 1D Array ?

---

<div class="post-metadata">

**Author:** ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)\
**Post date:** [November 6, 2018, 3:27pm UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/8 "2018-11-06T15:27:15Z")

</div>

The source file `reshapedarray.jl` uses a lot of splatting (that is, the … operation). The compiler uses a number of heuristics in decide when to specialize `...` versus when to punt and delay the type-matching until run-time. (The issue is that compile-time type-matching can be slow for complicated nested types like views of reshaped arrays.) It is possible that you have hit one of those cases when the compiler’s heuristic decides to punt the type-matching of indices to run-time. As far as I understand, there is no easy way with the available instrumentation tools to determine whether you are in that case. There are some techniques to prevent it. In another thread, Tim Holy said that you can sometimes force specialization of splatting by using `Varargs` instead. However, since the code with the splatting is in `Base` rather than your own file, this is not an option for you unless you decided to implement your own version of `reshape` and `view` specialized for your situation.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [November 6, 2018, 4:29pm UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/9 "2018-11-06T16:29:19Z")

</div>

> [@Stephen\_Vavasis](#):
>
> The source file `reshapedarray.jl` uses a lot of splatting

That’s not the problem here — and in general you shouldn’t worry or fear that the base library uses splatting. In cases like ReshapedArrays and SubArrays, we’ve taken great care to make sure that the splatting is “free.” Please don’t use such certainty about where you think the problem is when you’re not sure.

The problem is that we have two different versions of `permutedims!`:

```julia
julia> @which permutedims!(y3D,x3D,(2,3,1)) # This output is manually edited to use the StridedArray alias:
permutedims!(P::Array{T,N}, B::StridedArray{T,N}) where {T, N} in Base at multidimensional.jl:1273

julia> @which permutedims!(y3Dv,x3Dv,(2,3,1))
permutedims!(dest, src::AbstractArray, perm) in Base.PermutedDimsArrays at permuteddimsarray.jl:192

```

I think the multidimensional signature can actually be extended to be `(::StridedArray, ::StridedArray)`, and that’d fix the issue here:

```julia
julia> test()
time permutedims: 9.587e-6
time permutedims (view): 0.006955433
 slow down factor:725.5067278606446

# @eval Base permutedims!(::StridedArray, ::StridedArray)

julia> test()
time permutedims: 9.614e-6
time permutedims (view): 9.74e-6
 slow down factor:1.0131058872477636

```

Edit: I don’t think it even requires strided-ness. Just linear indexing is sufficient.

---

<div class="post-metadata">

**Author:** ![Stephen\_Vavasis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stephen_vavasis/32/3389_2.png) [@Stephen\_Vavasis](https://discourse.julialang.org/u/Stephen_Vavasis)\
**Post date:** [November 6, 2018, 4:46pm UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/10 "2018-11-06T16:46:51Z")

</div>

I didn’t mean to express any degree of certainty in my diagnosis of the problem-- indeed, I was just offering up a guess. Thank you for finding the correct diagnosis.

Following up on your comment, I’m glad to hear that splats in Base will all specialize as expected. I’m curious how this is achieved-- is there something in the Julia code itself to insist that these particular splats gets specialized? Or are the splats checked during the continuous-integration process via test sets? The reason I ask is because in other threads, posters have wondered about splats in their own codes.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [November 6, 2018, 6:35pm UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/11 "2018-11-06T18:35:40Z")

</div>

There are two potential sources for the “splatting penalty”:

- It might not be type stable. If you have a collection like `xs::Array` where the length isn’t encoded in the type itself, then Julia needs to use dynamic dispatch at runtime to figure out which method of `f` (how many args) to call in `f(xs…)`. This is by far the most common case that people run into.
- If the function `f` doesn’t get inlined or specialized, then Julia might need to gather up the elements of `xs` into a temporary heap-allocated object in order to call the function.

Both of these are carefully avoided with type-stable `Tuple`s (which know their length in their type) and with `@inline` or sometimes `Vararg` annotations throughout Base (like SubArray and ReshapedArray). There are times where we miss an inline or somesuch, but those are often easy to fix.

---

<div class="post-metadata">

**Author:** ![Sean\_McBane](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sean_mcbane/32/4580_2.png) [@Sean\_McBane](https://discourse.julialang.org/u/Sean_McBane)\
**Post date:** [November 6, 2018, 8:23pm UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/12 "2018-11-06T20:23:19Z")

</div>

Is benchmarking part of the CI process for new releases, to prevent performance regressions in Base?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [November 6, 2018, 8:25pm UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/13 "2018-11-06T20:25:33Z")

</div>

Yes.

---

<div class="post-metadata">

**Author:** ![LaurentPlagne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/laurentplagne/32/10103_2.png) [@LaurentPlagne](https://discourse.julialang.org/u/LaurentPlagne)\
**Post date:** [November 6, 2018, 10:25pm UTC](https://discourse.julialang.org/t/warning-for-array-view-usage/17189/14 "2018-11-06T22:25:13Z")

</div>

Thank you very much for these explanations.  
If I have correctly understood, the `view` use is correct and do not cause performance penalty if the `permutedim!` signature is extended.

Is this signature extension already planned ?
