# Broadcasting the reshaped data @. versus .=

**URL:** https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300
**Category:** General Usage
**Tags:** broadcasting, reshaping
**Created:** [December 31, 2024, 5:43am UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300 "2024-12-31T05:43:54Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![raman\_kumar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raman_kumar/32/26782_2.png) [@raman\_kumar](https://discourse.julialang.org/u/raman_kumar)
#### Post date: [December 31, 2024, 5:43am UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/1 "2024-12-31T05:43:54Z")

</div>

I am rewriting this code below using **broadcasting** to improve performance and clarity.

```julia
var = zeros(Float64, 9, 109, 50)
data = rand(9*109*50)
for j in 1:9
	# Extract the slice of data corresponding to the current `j`
	temp = data[((j-1)*109*50) + 1 : (j*109*50)]
	# Reshape the slice and directly assign it to `var`
	var[j, :, :] .= reshape(temp, 109, 50)
end

```

This code below gives error.

```julia
var = zeros(Float64, 9, 109, 50)
data = rand(9*109*50)
@. var = reshape(data, 9, 109, 50)

```

> ERROR: DimensionMismatch: array could not be broadcast to match destination  
> Stacktrace:  
> [1] check\_broadcast\_shape  
> @ ./broadcast.jl:547 [inlined]  
> [2] check\_broadcast\_axes  
> @ ./broadcast.jl:550 [inlined]  
> [3] check\_broadcast\_axes  
> @ ./broadcast.jl:553 [inlined]  
> [4] instantiate  
> @ ./broadcast.jl:305 [inlined]  
> [5] materialize!  
> @ ./broadcast.jl:878 [inlined]  
> [6] materialize!(dest::Array{…}, bc::Base.Broadcast.Broadcasted{…})  
> @ Base.Broadcast ./broadcast.jl:875  
> [7] top-level scope  
> @ REPL[10]:1  
> Some type information was truncated. Use `show(err)` to see complete types.

while following code below works fine but i see increase in memory allocation. Why above code gives error?

```julia
var = zeros(Float64, 9, 109, 50)
data = rand(9*109*50)
var .= reshape(data, 9, 109, 50)

```

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [December 31, 2024, 5:56am UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/2 "2024-12-31T05:56:00Z")

</div>

`@.` adds a dot to `reshape` as well

---

<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: [December 31, 2024, 9:07am UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/3 "2024-12-31T09:07:51Z")

</div>

Note that the loop and the broadcast expression do _not_ do the same thing. They copy over the data in different order. The loop will also by less efficient, since it doesn’t respect the memory layout of Arrays.

---

<div class="post-metadata">

### Author: ![raman\_kumar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raman_kumar/32/26782_2.png) [@raman\_kumar](https://discourse.julialang.org/u/raman_kumar)
#### Post date: [December 31, 2024, 3:56pm UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/4 "2024-12-31T15:56:38Z")

</div>

Yes, Broadcasting has better performance. I notice the performance changes in these codes.

```julia
@timev begin
	var = zeros(Float64, 9, 109, 50)
	data = rand(9*109*50)
	var .= reshape(data, 9, 109, 50)
end

@timev begin
	var = zeros(Float64, 9, 109, 50)
	data = rand(9*109*50)
	for j in 1:9
		temp = data[((j-1)*109*50) + 1 : (j*109*50)]
		var[j, :, :] .= reshape(temp, 109, 50)
	end
	var
end

```

---

<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: [December 31, 2024, 4:10pm UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/5 "2024-12-31T16:10:21Z")

</div>

> [@raman\_kumar](#):
>
> Yes, Broadcasting has better performance. I

It has nothing to do with broadcasting being faster than loops, you’re just doing the loop wrong, you must loop in correct, memory-friendly order.

E.g.

```julia
for i in eachindex(var, data) 
    var[i] = data[i]
end

```

---

<div class="post-metadata">

### Author: ![raman\_kumar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raman_kumar/32/26782_2.png) [@raman\_kumar](https://discourse.julialang.org/u/raman_kumar)
#### Post date: [December 31, 2024, 4:19pm UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/6 "2024-12-31T16:19:09Z")

</div>

> [@DNF](#):
>
> you’re just doing the loop wrong, you must loop in correct, memory-friendly order.

How should i do in my case? Can you explain in detail? In my case `for j in 1:9` there is no column-ordering issue. 🤔

---

<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: [December 31, 2024, 4:24pm UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/7 "2024-12-31T16:24:19Z")

</div>

It depends on what the correct order you want the data copied over. Your loop and your broadcast expression do it differently, so I don’t know which you actually want. But if the broadcasted version is the one you want (which is also the most efficient order) then do for example

> [@DNF](#):
>
> ```julia
> for i in eachindex(var, data) 
> var[i] = data[i]
> end
> 
> ```

for the loop, or

```julia
var[:] .= data

```

for broadcasting.

---

<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: [December 31, 2024, 4:29pm UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/8 "2024-12-31T16:29:19Z")

</div>

> [@raman\_kumar](#):
>
> In my case `for j in 1:9` there is no column-ordering issue. 🤔

Yes, there is. For performance, the loop over `j` should be the innermost loop, not the outermost. But, as I said, your loop code and your broadcasting code are copying the data differently, so you will get different results.

---

<div class="post-metadata">

### Author: ![raman\_kumar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raman_kumar/32/26782_2.png) [@raman\_kumar](https://discourse.julialang.org/u/raman_kumar)
#### Post date: [December 31, 2024, 4:39pm UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/9 "2024-12-31T16:39:21Z")

</div>

> [@DNF](#):
>
> But, as I said, your loop code and your broadcasting code are copying the data differently, so you will get different results.

Thanks for pointing out it to me. I would like to get data which i got using `for` loop but i also want to improve performance.

> [@DNF](#):
>
> `var[:] .= data`

😇 But on using broadcasting in way you suggested i got array instead of matrix. Please tell me proper way for broadcasting case.

```julia
@timev begin
	var = zeros(Float64, 9, 109, 50)
	data = rand(9*109*50)
	var[:] .= data
end

@timev begin
	for i in eachindex(var, data) 
    	var[i] = data[i]
	end
	var
end

```

I have an 1d array of data but i want to reshape it in a 3dim matrix.

---

<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: [December 31, 2024, 4:49pm UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/10 "2024-12-31T16:49:43Z")

</div>

Well, it’s not obvious. If you have some data, and you want to copy it somewhere else in non-contiguous order, then either the left-hand or right-hand side must be iterated in non-optimal order.

It is possible that your first piece of code is good, just slap a `@view` in front of the slice. But it requires testing to find the best alternative.

Oh, also make sure you put your code inside a function.

---

<div class="post-metadata">

### Author: ![raman\_kumar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raman_kumar/32/26782_2.png) [@raman\_kumar](https://discourse.julialang.org/u/raman_kumar)
#### Post date: [December 31, 2024, 5:03pm UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/11 "2024-12-31T17:03:51Z")

</div>

@DNF I would like to get data in pattern that i get using this `for` loop shown below. Your every suggestion gives different pattern.

```julia
for j in 1:9
	temp = data[((j-1)*109*50) + 1 : (j*109*50)]
	var[j, :, :] .= reshape(temp, 109, 50)
end

```

---

<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: [December 31, 2024, 5:28pm UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/12 "2024-12-31T17:28:38Z")

</div>

As I said, there are _two_ different patterns, and each of your code snippets produce one of each. I have not introduced any new patterns, only pointed out that your codes were not consistent.

Now that you have clarified which one you want, you can try

```julia
function mycopy!(var, data) 
    # don't hardcode 1:9, that will only work for one specific array
    N = size(var, 1) * size(var, 2)
    for j in axes(var, 1)  
    	temp = @view data[((j-1)*N) + 1 : j*N]
	    var[j, :] .= temp
    end
    return var
end

```

You could also try iterating over contiguous samples in `var` and discontinuous samples in `data` to see which is faster.

---

<div class="post-metadata">

### Author: ![raman\_kumar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/raman_kumar/32/26782_2.png) [@raman\_kumar](https://discourse.julialang.org/u/raman_kumar)
#### Post date: [January 1, 2025, 4:58am UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/13 "2025-01-01T04:58:08Z")

</div>

Your example don’t work. Actually i have to use `N = size(var, 2) * size(var, 3)` and `var[j,:,:] .= reshape(temp, 109, 50)` to get same output but there is no performance improvement.

```julia
@timev begin
	var = zeros(Float64, 9, 109, 50)
	data = rand(9*109*50)
	for j in 1:9
		temp = data[((j-1)*109*50) + 1 : (j*109*50)]
		var[j, :, :] .= reshape(temp, 109, 50)
	end
	var
end

@timev begin
    # don't hardcode 1:9, that will only work for one specific array
    N = size(var, 2) * size(var, 3)
    for j in axes(var, 1)  
    	temp = @view data[((j-1)*N) + 1 : j*N]
	    var[j,:,:] .= reshape(temp, 109, 50)
    end
    var
end

```

But this code below gives better performance.

```julia
@timev begin
    data = rand(9 * 109 * 50)
    reshaped_data = reshape(data, 109, 50, 9)
    var = permutedims(reshaped_data, (3, 1, 2))
end

```

Is there any better way to improve performance further? Thanks.

---

<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 1, 2025, 11:48am UTC](https://discourse.julialang.org/t/broadcasting-the-reshaped-data-versus/124300/14 "2025-01-01T11:48:39Z")

</div>

> [@DNF](#):
>
> `var[j, :] .= temp`

I was sure the above would work, by unravelling the trailing dimensions, just like `var[:]` does work, but apparently not. I did not have access to a computer to test, but I was completely certain.

A good solution then is to just make `temp` into a view, as you have in one of your snippets.

The snippet below does something different from your other snippets, it creates a _new_ array `var`, instead of writing in-place into a pre-existing array.

> [@raman\_kumar](#):
>
> ```julia
> @timev begin
> data = rand(9 * 109 * 50)
> reshaped_data = reshape(data, 109, 50, 9)
> var = permutedims(reshaped_data, (3, 1, 2))
> end
> 
> ```

It is indeed quite fast, though, and you can make it in-place by doing:

```julia
siz = size(var)
reshaped_data = reshape(data, siz[2], siz[3], siz[1])
permutedims!(var, reshaped_data, (3, 1, 2))

```

(note the trailing `!` in `permutedims!`)

Also note that your benchmarking is a bit suboptimal. Firstly, you are timing the the _creation_ of you input data as well as the copying code, which I assume is not desirable, and secondly, you should put your code in functions, like

```julia
function newcopy!(var, data)
    siz = size(var)
    permutedims!(var, reshape(data, siz[2], siz[3], siz[1]), (3, 1, 2))
    return var
end

```

and then benchmark passing the data as input

```julia
@time newcopy!(var, data)

```

Or, even better, use the BenchmarkTools.jl package. On my computer, `@timev` estimates 45us runtime for `newcopy!`, while `BencmarkTools.@btime` tells me 25us, which is probably more correct.
