# Preventing broadcast fusing

**URL:** <https://discourse.julialang.org/t/preventing-broadcast-fusing/20372>\
**Category:** General Usage\
**Tags:** broadcast\
**Created:** [February 2, 2019, 3:25am UTC](https://discourse.julialang.org/t/preventing-broadcast-fusing/20372 "2019-02-02T03:25:45Z")\
**Posts on this page:** 1\
**Showing post:** 18

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [February 3, 2019, 2:39am UTC](https://discourse.julialang.org/t/preventing-broadcast-fusing/20372/18 "2019-02-03T02:39:38Z")

</div>

> [@bennedich](#):
>
> But seeing code like that, it wouldn’t be obvious to me what’s going on. I’d probably opt for the 4 line version for more readability, especially since you say that " `a` is actually a more complicated expression itself with several operations fused together".
> 
> Alternatively, I’d add a comment like “identity is used to prevent too eager fusing” – to explain what’s going on, and prevent some too clever programmer seeing your code deciding to remove the “unnecessary” identity methods.

All excellent points and I’d probably do the same in production code.

> [@pengwyn](#):
>
> So given some optimisations to take account of pure functions, this kind of broadcast fusing would be handled at the loop level anyway?

The `identity` trick is manual loop “unfusing” and forces the allocation of a temporary array, exactly like making the temporary explicitly on a separate line. Deciding on which parts of a broadcast would better be materialized early, stored and reused in a separate loop is an optimization which depends on pretty high level knowledge of the cost of memory allocation, memory bandwidth vs the cost of redoing some computation in the inner loop. And these things also completely depend on the size of the arrays involved. I don’t expect the julia compiler to do this any time soon and it also seems at odds with the simple definition of broadcasting which we have now as a fully fused operation.

If I understand LICM correctly it’s a much more local optimization which given a loop structure decides which parts may be hoisted out as loop invariants. It would definitely help here (if it’s not done already), as it allows the following transformation

```julia
for i=1:n
    for j=1:n
        for k=1:n
            out[i,j,k] = exp(x[i]) * exp(y[j]) * exp(z[k])
        end
    end
end

```

to

```julia
for i=1:n
    ex = exp(x[i])
    for j=1:n
        ey = exp(y[j])
        for k=1:n
            out[i,j,k] = ex * ey * exp(z[k])
        end
    end
end

```

But even so, you’ve still got `O(n^3)` invocations of `exp`, whereas allocating temporary storage and splitting the loops brings you down to `O(n)`.

---

_[View the full topic](https://discourse.julialang.org/t/preventing-broadcast-fusing/20372)._
