# Deferred-shape arrays

**URL:** <https://discourse.julialang.org/t/deferred-shape-arrays/48177>\
**Category:** Internals & Design\
**Tags:** question\
**Created:** [October 11, 2020, 7:58pm UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177 "2020-10-11T19:58:08Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![xanfus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xanfus/32/5813_2.png) [@xanfus](https://discourse.julialang.org/u/xanfus)\
**Post date:** [October 11, 2020, 7:58pm UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177/1 "2020-10-11T19:58:08Z")

</div>

Does Julia have deferred-shape array type like in Fortran? The feature can reduce clogging in main function by taking care of variable declarations somewhere else, if variables have parametric dimensions.  
[https://www.ibm.com/support/knowledgecenter/SSGH4D\_15.1.2/com.ibm.xlf151.aix.doc/language\_ref/defrshp.html](https://www.ibm.com/support/knowledgecenter/SSGH4D_15.1.2/com.ibm.xlf151.aix.doc/language_ref/defrshp.html)

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [October 12, 2020, 11:28am UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177/2 "2020-10-12T11:28:56Z")

</div>

I am not sure why you need this in Julia, which does not require that you declare variables.

Please provide an MWE with some context to clarify.

> [@Please read: make it easier to help you](https://discourse.julialang.org/t/psa-make-it-easier-to-help-you/14757/):
>
> Welcome to the Julia Discourse! We are enthusiastic about helping Julia programmers, both beginner and experienced. This public service announcement (PSA) outlines best practices when asking for help. Following these points makes it easier for us to help you and more likely you’ll get a prompt, useful answer. Keywords are highlighted to make it easier to refer to specific points. Choose a descriptive title that captures the key part of your question, eg “plots with multiple axes” instead of …

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 12, 2020, 8:42pm UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177/3 "2020-10-12T20:42:13Z")

</div>

In general, if some code doesn’t care about the shape of an array, it can just not say anything about it. If you want to access the same array data with different shape, you can use `reshape`. Between those features, it seems like everything you might want to do would be covered.

---

<div class="post-metadata">

**Author:** ![traktofon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/traktofon/32/591_2.png) [@traktofon](https://discourse.julialang.org/u/traktofon)\
**Post date:** [October 13, 2020, 11:50am UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177/4 "2020-10-13T11:50:08Z")

</div>

`reshape` still causes a (small) allocation for the reshaped view, doesn’t it? Since Julia 1.5, these kind of small allocations for `view`s have been eliminated (as long as the `view` doesn’t “escape”) but in my tests even with Julia 1.6-dev a `reshape` still allocates. Is there hope that those allocations can be avoided in the future, like for `view`s?

For completeness:

```julia
using BenchmarkTools
function sum_as_mtx(A)
   B = reshape(A, (20,10))
   sum(B)
end
A = randn(200)
@btime sum_as_mtx($A)
# 52.413 ns (1 allocation: 64 bytes)

```

---

<div class="post-metadata">

**Author:** ![xanfus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/xanfus/32/5813_2.png) [@xanfus](https://discourse.julialang.org/u/xanfus)\
**Post date:** [October 13, 2020, 1:13pm UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177/5 "2020-10-13T13:13:07Z")

</div>

Variable declaration undergoes implicitly, in my comprehension. Compiler infers variable type, primitive or composite or “Any” or “Core.Box”.  
I suppose, i can obtain deferred-shape array in a way, in Julia. I can create _constant_ global array A, which is exported and used from within any scope. Variable name “A” can be then reassigned to array of same type of element and number of dimensions but new length along each dimension. A warning will rise. Hadn’t tried it myself. I want to think, array A will be then present with new shape everywhere it was imported before reassignment.

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [October 13, 2020, 1:24pm UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177/6 "2020-10-13T13:24:34Z")

</div>

`Array` is a special case, as revealed by `methods(reshape)` (easiest if you have no other packages loaded, since some add their own methods). Most other array types go through `ReshapedArray`, which can have a 0-allocation wrapper:

```julia
julia> @btime reshape($A, (10, 20));
  34.681 ns (1 allocation: 64 bytes)

julia> @btime Base.ReshapedArray($A, (10, 20), ());
  6.600 ns (0 allocations: 0 bytes)

```

I wonder if it’s time to reconsider this choice.

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [October 13, 2020, 2:51pm UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177/7 "2020-10-13T14:51:13Z")

</div>

Ironic (and great) that the language has gotten so good that the user-defined thing is better than the built-in thing now! Reminds me of back in 0.2 (IIRC), when immutable structs were added and they were immediately better than tuples because they allowed inline storage of immutable fields whereas tuples of the time always consisted of pointers to boxed values.

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [October 13, 2020, 3:03pm UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177/8 "2020-10-13T15:03:48Z")

</div>

`ReshapedArray` seems quite a bit slower to read from, but is this a fair test?

```julia
julia> A = rand(2000); B = zeros(100,20);

julia> @btime $B .= reshape($A, (100, 20));
  276.312 ns (1 allocation: 64 bytes)

julia> @btime $B .= Base.ReshapedArray($A, (100, 20), ());
  529.658 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![simeonschaub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simeonschaub/32/216566_2.png) [@simeonschaub](https://discourse.julialang.org/u/simeonschaub)\
**Post date:** [October 13, 2020, 3:11pm UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177/9 "2020-10-13T15:11:59Z")

</div>

This is also related to [https://github.com/JuliaLang/julia/issues/37888](https://github.com/JuliaLang/julia/issues/37888). I feel like these allocations should be avoidable, but one would need to figure out how to avoid allocating pointers in the ccall.

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [October 13, 2020, 3:36pm UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177/10 "2020-10-13T15:36:08Z")

</div>

Yeah, it’s a fair test, though it may be avoidable. The `::Array` variant spends its time in `unsafe_copyto!` (specifically [https://github.com/JuliaLang/julia/blob/a1da84c3b0406e8378d8af781fe74ce749725d1f/base/array.jl#L293-L294](https://github.com/JuliaLang/julia/blob/a1da84c3b0406e8378d8af781fe74ce749725d1f/base/array.jl#L293-L294)) whereas the `::ReshapedArray` variant spends its time in `copyto_unaliased!` ([https://github.com/JuliaLang/julia/blob/a1da84c3b0406e8378d8af781fe74ce749725d1f/base/abstractarray.jl#L919-L921](https://github.com/JuliaLang/julia/blob/a1da84c3b0406e8378d8af781fe74ce749725d1f/base/abstractarray.jl#L919-L921)).

```julia
julia> using BenchmarkTools

julia> A = rand(2000); B = zeros(100,20);

julia> @btime $B .= reshape($A, (100, 20));
  234.554 ns (1 allocation: 64 bytes)

julia> @btime $B .= Base.ReshapedArray($A, (100, 20), ());
  991.833 ns (0 allocations: 0 bytes)

julia> Revise.track(Base) # add @simd inside copyto_unaliased!

julia> @btime $B .= reshape($A, (100, 20));
  232.961 ns (1 allocation: 64 bytes)

julia> @btime $B .= Base.ReshapedArray($A, (100, 20), ());
  192.912 ns (0 allocations: 0 bytes)

```

Want to PR it?

---

<div class="post-metadata">

**Author:** ![mcabbott](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mcabbott/32/6603_2.png) [@mcabbott](https://discourse.julialang.org/u/mcabbott)\
**Post date:** [October 13, 2020, 3:55pm UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177/11 "2020-10-13T15:55:32Z")

</div>

OK, that’s simple, done, #38014.

Trying to test scalar access… any idea here?

```julia
julia> @btime sum(x for x in view($(reshape(A, (100, 20))),20,:));
  11.289 ns (0 allocations: 0 bytes)

julia> @btime sum(x for x in view($(Base.ReshapedArray(A, (100, 20), ())),20,:));
  15.275 ns (0 allocations: 0 bytes)

```

---

<div class="post-metadata">

**Author:** ![tim.holy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tim.holy/32/52_2.png) [@tim.holy](https://discourse.julialang.org/u/tim.holy)\
**Post date:** [October 13, 2020, 3:58pm UTC](https://discourse.julialang.org/t/deferred-shape-arrays/48177/12 "2020-10-13T15:58:33Z")

</div>

Can’t look now, but what I do is put a `@profile` in front of that `@btime` and then check the result, ignoring all the `gcscrub` and inference that `@btime` triggers.
