# Speeding up summation inside comprehension

**URL:** <https://discourse.julialang.org/t/speeding-up-summation-inside-comprehension/39119>\
**Category:** Performance\
**Created:** [May 8, 2020, 4:31pm UTC](https://discourse.julialang.org/t/speeding-up-summation-inside-comprehension/39119 "2020-05-08T16:31:04Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![gobs](https://avatars.discourse-cdn.com/v4/letter/g/bc8723/32.png) [@gobs](https://discourse.julialang.org/u/gobs)\
**Post date:** [May 8, 2020, 4:31pm UTC](https://discourse.julialang.org/t/speeding-up-summation-inside-comprehension/39119/1 "2020-05-08T16:31:04Z")

</div>

I currently do something similar to the code below (though I have axis arrays instead of regular arrays):

```julia
A = 1:100
B = 1:200
C = 1:300

x = rand(length(A),length(B),length(C))
y = rand(length(B),length(C))

z = [
    sum(y[b,c]*x[a,b,c] for b=B)
    for a=A, c=C
]

```

I can see this potentially taking a very long time if my dimensions (A, B and C) get bigger, which they will eventually.

I know that in 2 dimensions I could do a vector/matrix operation which would be faster if I have a multi threaded processor (if I understand correctly), like the following:

```julia
x = rand(length(B), length(A))
y = rand(length(B), 1)
z = y' * x

```

I was wondering if there’s an obvious way to do that for the first example?

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [May 8, 2020, 4:45pm UTC](https://discourse.julialang.org/t/speeding-up-summation-inside-comprehension/39119/2 "2020-05-08T16:45:37Z")

</div>

This is like 4x faster on my machine, could definitely be improved still.

```julia
hcat([view(x,:,:,c)*view(y,:,c) for c in C]...)

```

---

<div class="post-metadata">

**Author:** ![gobs](https://avatars.discourse-cdn.com/v4/letter/g/bc8723/32.png) [@gobs](https://discourse.julialang.org/u/gobs)\
**Post date:** [May 8, 2020, 4:52pm UTC](https://discourse.julialang.org/t/speeding-up-summation-inside-comprehension/39119/3 "2020-05-08T16:52:09Z")

</div>

Cool! I didn’t know about the `view` function. I’ll try and adapt it to my code.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [May 8, 2020, 4:57pm UTC](https://discourse.julialang.org/t/speeding-up-summation-inside-comprehension/39119/4 "2020-05-08T16:57:12Z")

</div>

This is a tensor contraction, so maybe you can use [https://github.com/Jutho/TensorOperations.jl](https://github.com/Jutho/TensorOperations.jl)

---

<div class="post-metadata">

**Author:** ![gobs](https://avatars.discourse-cdn.com/v4/letter/g/bc8723/32.png) [@gobs](https://discourse.julialang.org/u/gobs)\
**Post date:** [May 8, 2020, 5:05pm UTC](https://discourse.julialang.org/t/speeding-up-summation-inside-comprehension/39119/5 "2020-05-08T17:05:36Z")

</div>

Thanks for the recomendation! I implemented tbeason’s use of view and actually got a ~ 20 times speed up, so that’s good enough for me. Makes me want to go through my code and figure out what else I can improve…

---

<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:** [May 8, 2020, 6:30pm UTC](https://discourse.julialang.org/t/speeding-up-summation-inside-comprehension/39119/6 "2020-05-08T18:30:27Z")

</div>

This one isn’t handled by TensorOperations:

```julia
TensorOperations.@tensor z[a,c] := y[b,c] * x[a,b,c] # IndexError{String}("non-matching indices

```

but it can be done with various other packages:

```julia
Einsum.@einsum z1[a,c] := y[b,c] * x[a,b,c]
OMEinsum.@ein z2[a,c] := y[b,c] * x[a,b,c]
TensorCast.@reduce z3[a,c] := sum(b) y[b,c] * x[a,b,c]
Tullio.@tullio z4[a,c] := y[b,c] * x[a,b,c]

z5 = reshape(NNlib.batched_mul(x, reshape(y,200,1,300)), 100,300)
z ≈ z1 ≈ z2 ≈ z3 ≈ z4 ≈ z5

```
