# Preventing collect on broadcasting expressions

**URL:** <https://discourse.julialang.org/t/preventing-collect-on-broadcasting-expressions/57996>\
**Category:** General Usage\
**Tags:** broadcast, broadcasting, collection\
**Created:** [March 26, 2021, 8:21am UTC](https://discourse.julialang.org/t/preventing-collect-on-broadcasting-expressions/57996 "2021-03-26T08:21:19Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)\
**Post date:** [March 26, 2021, 8:21am UTC](https://discourse.julialang.org/t/preventing-collect-on-broadcasting-expressions/57996/1 "2021-03-26T08:21:19Z")

</div>

In writing efficient code for image processing, views are incredibly useful. They can nicely be chained for example to implement a phasor in optics propagation:

```julia
using IndexFunArrays
k0 = 5; phasor = exp.(1im .* 2pi .*sqrt.(k0^2 .- rr2((7,7))))
7×7 Matrix{ComplexF64}:

```

But the the `phasor` is again just a nother builden block in further expressions and it might be nice to intentionally keep it from being evaluated at definition. In other words I would like the broadcast / loop fusion operation to not automatically evaluate but rather encapsulate it in a view. I tried `view(myexpression)`  
Yet this yields `ERROR: BoundsError: attempt to access 7×7 Matrix{ComplexF64} at index []`. Is there any known convenient way to prevent loop evaluation?  
One may think that `view()` might do the job. But there are two problems: 1. `view` cannot be called with only a single array element, but always seems to require ranges which means at least the number of dimension needs be known. 2. The argument of view is also fused and evaluated if it contains such a fusion operation:

```julia
@time v = view(rr2((3000,3000)) .+ 0,:,:);
  0.046590 seconds (9 allocations: 68.665 MiB, 43.28% gc time)
 @time v = view(rr2((3000,3000)),:,:);
  0.000023 seconds (7 allocations: 336 bytes)

```

Any ideas how to prevent loop fusion upon assignment?

---

<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:** [March 26, 2021, 11:15am UTC](https://discourse.julialang.org/t/preventing-collect-on-broadcasting-expressions/57996/2 "2021-03-26T11:15:37Z")

</div>

See eg `BroadcastArray` in

> **[GitHub - JuliaArrays/LazyArrays.jl: Lazy arrays and linear algebra in Julia](https://github.com/JuliaArrays/LazyArrays.jl)**
>
> Lazy arrays and linear algebra in Julia. Contribute to JuliaArrays/LazyArrays.jl development by creating an account on GitHub.

---

<div class="post-metadata">

**Author:** ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)\
**Post date:** [March 26, 2021, 3:33pm UTC](https://discourse.julialang.org/t/preventing-collect-on-broadcasting-expressions/57996/3 "2021-03-26T15:33:56Z")

</div>

Thanks for the quick answer. I might be missing something here, but in my hands this never worked:

```julia
@time q = BroadcastArray(+, ones((3000,3000)), 0.0);
  0.039350 seconds (3 allocations: 68.665 MiB, 46.17% gc time)

```

It works if there are allocate operations, but the broadcasting seems incabable of dealing with on-the-fly generators like `ones` or `rr2`.

---

<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:** [March 26, 2021, 3:44pm UTC](https://discourse.julialang.org/t/preventing-collect-on-broadcasting-expressions/57996/4 "2021-03-26T15:44:37Z")

</div>

`BroadcastArray` still evaluates its arguments, so it can’t remove the allocation of `ones`. For that you could in theory use FillArrays.jl, but there appears to be some awkward interaction between how the two packages alter broadcasting:

```julia
julia> using LazyArrays, FillArrays

julia> o3k = ones((3000,3000));

julia> @time q = BroadcastArray(@~ o3k .+ 1.0);
  0.000028 seconds (6 allocations: 208 bytes)

julia> Fill(1.0, 3000, 3000) .+ 1.0
3000×3000 Fill{Float64, 2, Tuple{OneTo{Int64}, OneTo{Int64}}} = 2.0

julia> @time q = BroadcastArray(+, Fill(1.0, 3000, 3000), 1.0);
ERROR: type Fill has no field f

```

---

<div class="post-metadata">

**Author:** ![RainerHeintzmann](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rainerheintzmann/32/19726_2.png) [@RainerHeintzmann](https://discourse.julialang.org/u/RainerHeintzmann)\
**Post date:** [March 26, 2021, 4:31pm UTC](https://discourse.julialang.org/t/preventing-collect-on-broadcasting-expressions/57996/5 "2021-03-26T16:31:44Z")

</div>

Thanks. But the whole point of this thread was to be able to chain operations that are capable to generate data on the fly (like rr2() or also ones()) together across multiple lines. Not as a default behaviour but on purpose. FillArrays seem to be a special case, as they essentially host only a single value and broadcasting needs to be applied to this one value only. So this is probably the way they achieve it there, but this breaks down quickly:

```julia
a = Fill(1.0,3000,3000) .* ones(3000,3000)
3000×3000 Matrix{Float64}:

```

Theoretically it is still one value but the mechanism is naturally incapable of seeing this.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [March 26, 2021, 4:58pm UTC](https://discourse.julialang.org/t/preventing-collect-on-broadcasting-expressions/57996/6 "2021-03-26T16:58:16Z")

</div>

@RainerHeitzmann, this discussion is well above my level but luck is a factor helping beginners, sometimes.

Does this function composition make sense?

```julia
using IndexFunArrays
k0 = 5; 
phasor(r) = exp.(1im .* 2pi .*sqrt.(k0^2 .- r))

n = 7; m = 7;
ph = IndexFunArray(phasor ∘ rr2,(n,m))

7×7 IndexFunArray{Matrix{ComplexF64}, 2, ComposedFunction{typeof(phasor), typeof(rr2)}}:

```

---

<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:** [March 27, 2021, 2:22pm UTC](https://discourse.julialang.org/t/preventing-collect-on-broadcasting-expressions/57996/7 "2021-03-27T14:22:20Z")

</div>

> [@RainerHeintzmann](#):
>
> but the mechanism is naturally incapable of seeing this

I am not sure what “mechanism” you are expecting here. In any case,

```julia
julia> Fill(1.0,3000,3000) .* Fill(1.0, 3000,3000)
3000×3000 Fill{Float64}: entries equal to 1.0

```

works. Once the bug mentioned by @mcabbott is fixed, it should work fine for your purposes.
