# Custom reshape() function for specific usage

**URL:** https://discourse.julialang.org/t/custom-reshape-function-for-specific-usage/113382
**Category:** Performance
**Tags:** array, memory, memory-allocation, tensors, tensoroperations
**Created:** [April 23, 2024, 9:28am UTC](https://discourse.julialang.org/t/custom-reshape-function-for-specific-usage/113382 "2024-04-23T09:28:15Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![Harrykjg-physics](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/harrykjg-physics/32/208708_2.png) [@Harrykjg-physics](https://discourse.julialang.org/u/Harrykjg-physics)
#### Post date: [April 23, 2024, 9:28am UTC](https://discourse.julialang.org/t/custom-reshape-function-for-specific-usage/113382/1 "2024-04-23T09:28:15Z")

</div>

Hi there ! Is there any way to minimize the **memory usage** of the following custom function **graded\_reshape()** ( Or even achieve the same performance as the Julia **reshape** function ) ?

Suppose we have a usual Julia reshape function which receives Array like **rand(10, 10, 10, 10)** and do the following reshaping :

```
    function usual_reshape(A)
       C = reshape(A, (10, 100, 10))
       return C
    end

```

But instead of naive reshaping above, we want to achieve the following **graded\_reshape()** function :

```
    function graded_reshape(A)
        B1 = A[:, 1:6, 1:6, :]
        B2 = A[:, 7:10, 7:10, :]
        B3 = A[:, 1:6, 7:10, :]
        B4 = A[:, 7:10, 1:6, :]
        C1 = reshape(B1 , (10, 36, 10))
        C2 = reshape(B2, (10, 16, 10)) 
        C3 = reshape(B3, (10, 24, 10))
        C4 = reshape(B4, (10, 24, 10))
        C = cat(C1, C2, C3, C4; dims=2)
        return C

     end

```

The latter function has more memory allocations due to the **cat** function :

```
    A = rand(10, 10, 10, 10)
    @btime usual_reshape($A)

```

25.148 ns (2 allocations: 96 bytes)

```
    @btime graded_reshape($A)

```

23.406 μs (61 allocations: 158.50 KiB)

Note that the size after reshaping is the same for **reshape()** and **graded\_reshape()**, i.e. (10, 100, 10). While the latter one adjust the elements within the reshaped dimension.

Is there any good idea ? Thanks in advance !!!

---

<div class="post-metadata">

### Author: ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)
#### Post date: [April 23, 2024, 11:44am UTC](https://discourse.julialang.org/t/custom-reshape-function-for-specific-usage/113382/2 "2024-04-23T11:44:34Z")

</div>

> Or even achieve the same performance as the Julia **reshape** function ?

A julia array is a blob of memory, plus some metadata that signifies the meaning of that data.

The julia reshape function is so fast because no data is copied – we’re just wrapping different metadata around the same blob of memory. Since the reshaped array references the same data, it will change along if the original array is modified.

So you should not think in terms of multi-dimensional arrays / tensors (4 indices) but rather in terms of one-dimensional arrays (Vectors / blobs of memory), with convenience functions that compute a 1-d index from the 4d index. In other words, the fast reshape is effectively a no-op / view.

For example for 4-tensors,

```julia
A[i+1, j+1, k+1, ell+1] == A[1 + i + size(A,1)*j + size(A,1) * size(A,2) * k + size(A,1) * size(A,2) * size(A,3) * ell]

```

So you need to think about whether that can work for you – if the input / output memory layouts are the same then there is a fast reshape, otherwise you need to allocate and copy. This is not a limitation of the julia language, it is a limitation of linear memory addressing (special purpose hardware contexts with multi-dimensional memory addressing are relatively rare).

---

<div class="post-metadata">

### Author: ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)
#### Post date: [April 25, 2024, 4:54am UTC](https://discourse.julialang.org/t/custom-reshape-function-for-specific-usage/113382/3 "2024-04-25T04:54:00Z")

</div>

> [@Harrykjg-physics](#):
>
> `A[:, 1:6, 1:6, :]`

Note that in Julia this makes a copy of the array. Maybe you could avoid some allocation by using views instead, e.g. try

```julia
function graded_reshape(A)
        B1 = @view A[:, 1:6, 1:6, :]
        B2 = @view A[:, 7:10, 7:10, :]
        B3 = @view A[:, 1:6, 7:10, :]
        B4 = @view A[:, 7:10, 1:6, :]
        C1 = reshape(B1 , (10, 36, 10))
        C2 = reshape(B2, (10, 16, 10)) 
        C3 = reshape(B3, (10, 24, 10))
        C4 = reshape(B4, (10, 24, 10))
        C = cat(C1, C2, C3, C4; dims=2)
        return C
     end

```

Alternatively, maybe you could choose a better data representation that allows for this transformation more naturally than using a single array.

---

<div class="post-metadata">

### Author: ![Harrykjg-physics](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/harrykjg-physics/32/208708_2.png) [@Harrykjg-physics](https://discourse.julialang.org/u/Harrykjg-physics)
#### Post date: [April 25, 2024, 9:14am UTC](https://discourse.julialang.org/t/custom-reshape-function-for-specific-usage/113382/4 "2024-04-25T09:14:10Z")

</div>

Thanks for your kind reply. The use of @view is indeed crucial when doing slicing. But as you and @foobar_lv2 all mentioned, I guess a better design of the underlying data representation should be more essential to my problem. I might think it more carefully.

I guess [TensorKit.jl](https://jutho.github.io/TensorKit.jl/stable/) has some possible optimizations closely related to my problem (where they fuse two indices with Z2 symmetry), so I need to take time and read its implementations.
