# Using Threads.@spawn with BLAS.set\_num\_threads

**URL:** <https://discourse.julialang.org/t/using-threads-spawn-with-blas-set-num-threads/139865>\
**Category:** General Usage\
**Created:** [October 6, 2026, 8:51pm UTC](https://discourse.julialang.org/t/using-threads-spawn-with-blas-set-num-threads/139865 "2026-10-06T20:51:27Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Uve](https://avatars.discourse-cdn.com/v4/letter/u/82dd89/32.png) [@Uve](https://discourse.julialang.org/u/Uve)\
**Post date:** [October 6, 2026, 8:51pm UTC](https://discourse.julialang.org/t/using-threads-spawn-with-blas-set-num-threads/139865/1 "2026-10-06T20:51:27Z")

</div>

Hi,

I’m implementing a frequency sweep algorithm. In each iteration, two reduced models are evaluated on a grid of candidate points. Since each candidate frequency is evaluated independently of the others, I can evaluate them in different tasks.

The issue is that the evaluations involve BLAS operations. I ran some tests, and in general, when I increase the number of tasks into which i split the candidates, I get slightly better perfomance when I set the number of BLAS threads to 1.

The pseudocode would look something like this:

```julia

function with_BLAS_num_threads(f::F,n::Integer=1) where F
    previous=BLAS.get_num_threads()
    previous==n && return f()
    try
        BLAS.set_num_threads(n)
        return f()
    finally
        BLAS.set_num_threads(previous)
    end
end

# I can use ChunkSplitters.jl
function pseudo_errors!(errors, candidates, E_r1, A_r1, B_r1, C_r1, E_r2, A_r2, B_r2, C_r2, Δf, nthreads)
    n = length(candidates)
    chunk_size = ceil(Int, n / nthreads)
    tasks = map(1:nthreads) do t
        Threads.@spawn begin
            # allocate matrices
            H1 = # ...
            chunk = (t-1)*chunk_size+1 : min(t*chunk_size, n)
            for idx in chunk
                fi = candidates[idx]
                # compute s1 and s2
                eval_reduced_model!(H1, args1...) #
                eval_reduced_model!(H2, args2...)
                errors[idx] = # something
            end
        end
    end
    foreach(wait, tasks)
    return errors
end

with_BLAS_num_threads(1) do
    pseudo_errors!(errors, candidates, E_r1, A_r1, B_r1, C_r1, E_r2, A_r2, B_r2, C_r2, Δf, nthreads)
end

```

My main interest isn’t performance, since I can benchmark that and determine whether the trade off is worthwhile. My main concern is whether there are any issues with this type of pattern.

- Are there any side effects or issues that I might be overlooking?
- Is there a more convenient or suitable pattern for this type of problem?

I’m interested in hearing how people would approach this in Julia, and whether there are any unexpected issues with this pattern that I should be aware of.

---

<div class="post-metadata">

**Author:** ![sgaure](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sgaure/32/14779_2.png) [@sgaure](https://discourse.julialang.org/u/sgaure)\
**Post date:** [October 6, 2026, 9:52pm UTC](https://discourse.julialang.org/t/using-threads-spawn-with-blas-set-num-threads/139865/2 "2026-10-06T21:52:53Z")

</div>

The pattern seems fine. Just a couple of comments.

There’s a function `cld` which you can use like `chunk_size = cld(n, nthreads)` to avoid possible problems with rounding (e.g. `n/nthreads = 6.000000000001`)

Your last chunk may end up very small. There’s a simple package ChunkSplitters.jl which balances the chunk sizes better. An alternative is taking indices one by one:

```julia-auto
idxs = Atomic{Int}(1)
...
    @spawn begin
    ...
    while (idx = atomic_add!(idxs, 1)) <= n)
        ...
    end

```

Or have the chunk\_size a variable:

```julia-auto
while (lastidx = atomic_add!(idxs, chunk_size)) 
    for idx in lastidx-chunk_size+1:lastidx
        ...
    end

```

It’s also possible to decrease the chunk size as one approaches the end, but that requires the chunk\_size to be atomic as well, and some care must be taken.
