# Parallelization efficiency for @tensor @tullio

**URL:** <https://discourse.julialang.org/t/parallelization-efficiency-for-tensor-tullio/101021>\
**Category:** Numerics\
**Created:** [June 30, 2023, 3:16pm UTC](https://discourse.julialang.org/t/parallelization-efficiency-for-tensor-tullio/101021 "2023-06-30T15:16:05Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nellatur](https://avatars.discourse-cdn.com/v4/letter/n/76d3ee/32.png) [@Nellatur](https://discourse.julialang.org/u/Nellatur)\
**Post date:** [June 30, 2023, 3:16pm UTC](https://discourse.julialang.org/t/parallelization-efficiency-for-tensor-tullio/101021/1 "2023-06-30T15:16:05Z")

</div>

For the input

```julia
using TensorOperations
using LinearAlgebra
using BenchmarkTools
using Tullio

A = rand(1000, 1000)
B = rand(1000, 1000)

@btime @tensor C[i,k] := A[i,j]*B[j,k]
@btime @tullio C[i,k] := A[i,j]*B[j,k]

```

I use `export JULIA_NUM_THREADS=1` and `export JULIA_NUM_THREADS=6` to set up parallel, I got

```julia
22.056 ms (3 allocations: 7.63 MiB)
  731.924 ms (2 allocations: 7.63 MiB)

```

and

```julia
  22.146 ms (3 allocations: 7.63 MiB)
  129.130 ms (77 allocations: 7.63 MiB)

```

there is not an acceleration in @tensor. @tullio there is acceleration, but much slower than @tensor. Is there any way to speed up @tensor or using other package?

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [June 30, 2023, 4:12pm UTC](https://discourse.julialang.org/t/parallelization-efficiency-for-tensor-tullio/101021/2 "2023-06-30T16:12:09Z")

</div>

Just checked

```julia
using TensorOperations
using LinearAlgebra
using LoopVectorization
using BenchmarkTools

function mat_mul_1(A, B)
    @tensor C[i,k] := A[i,j]*B[j,k]
    return C
end
function mat_mul_2(A, B)
    C = A * B
    return C
end   

@btime mat_mul_1(A, B) setup=(A = rand(1000, 1000); B = rand(1000, 1000))
@btime mat_mul_2(A, B) setup=(A = rand(1000, 1000); B = rand(1000, 1000))

```

returning

```julia
  9.764 ms (2 allocations: 7.63 MiB)
  9.774 ms (2 allocations: 7.63 MiB)

```

Looks too me like @tensor is doing the right thing™ already.

---

<div class="post-metadata">

**Author:** ![Nellatur](https://avatars.discourse-cdn.com/v4/letter/n/76d3ee/32.png) [@Nellatur](https://discourse.julialang.org/u/Nellatur)\
**Post date:** [June 30, 2023, 4:30pm UTC](https://discourse.julialang.org/t/parallelization-efficiency-for-tensor-tullio/101021/3 "2023-06-30T16:30:45Z")

</div>

Thanks. But, how to use more cores to speed up @tensor?

---

<div class="post-metadata">

**Author:** ![goerch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goerch/32/29122_2.png) [@goerch](https://discourse.julialang.org/u/goerch)\
**Post date:** [June 30, 2023, 5:00pm UTC](https://discourse.julialang.org/t/parallelization-efficiency-for-tensor-tullio/101021/4 "2023-06-30T17:00:33Z")

</div>

The operation could be multithreaded already if it is dispatched to BLAS, see [BLAS.set\_num\_threads](https://docs.juliahub.com/ITensors/P3pqL/0.1.40/Multithreading.html). So I wouldn’t expect to get more performance here.

---

<div class="post-metadata">

**Author:** ![Nellatur](https://avatars.discourse-cdn.com/v4/letter/n/76d3ee/32.png) [@Nellatur](https://discourse.julialang.org/u/Nellatur)\
**Post date:** [June 30, 2023, 5:59pm UTC](https://discourse.julialang.org/t/parallelization-efficiency-for-tensor-tullio/101021/5 "2023-06-30T17:59:12Z")

</div>

Thank you so much. After adding

```julia
BLAS.set_num_threads(2)

```

it indeed gets faster!

```julia
 12.883 ms (3 allocations: 7.63 MiB)
  836.022 ms (2 allocations: 7.63 MiB)

```

BLAS.set\_num\_threads(4)

```julia
 6.593 ms (3 allocations: 7.63 MiB)
  792.141 ms (2 allocations: 7.63 MiB)

```

it seems @tensor depends on `BLAS.set_num_threads`, @tullio depends on `export JULIA_NUM_THREADS=`

---

<div class="post-metadata">

**Author:** ![Elrod](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/elrod/32/22461_2.png) [@Elrod](https://discourse.julialang.org/u/Elrod)\
**Post date:** [June 30, 2023, 6:02pm UTC](https://discourse.julialang.org/t/parallelization-efficiency-for-tensor-tullio/101021/6 "2023-06-30T18:02:32Z")

</div>

Try `using Tullio, LoopVectorization`. This should speed it up.

```julia
julia> using Tullio, TensorOperations, LinearAlgebra

julia> BLAS.set_num_threads(@show(Threads.nthreads()));
Threads.nthreads() = 8

julia> A = rand(1000,1000); B = rand(1000,1000); C = similar(A);

julia> @btime @tensor $C[i,k] = $A[i,j]*$B[j,k];
  2.575 ms (0 allocations: 0 bytes)

julia> @btime @tullio $C[i,k] = $A[i,j]*$B[j,k];
  92.953 ms (114 allocations: 5.94 KiB)

julia> using LoopVectorization

julia> @btime @tullio $C[i,k] = $A[i,j]*$B[j,k];
  3.956 ms (115 allocations: 5.97 KiB)

```

`@tensor` still wins for me, but `@tullio` at least improves a lot.  
`@tullio` is pure Julia, which is why it relies on Julia threads, and needs `LoopVectorization` for good performance on the CPU.
