# Pattern for managing thread local storage?

**URL:** <https://discourse.julialang.org/t/pattern-for-managing-thread-local-storage/54023>\
**Category:** General Usage\
**Tags:** question, multithreading\
**Created:** [January 27, 2021, 1:08am UTC](https://discourse.julialang.org/t/pattern-for-managing-thread-local-storage/54023 "2021-01-27T01:08:23Z")\
**Posts on this page:** 1\
**Showing post:** 2

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [January 27, 2021, 9:05am UTC](https://discourse.julialang.org/t/pattern-for-managing-thread-local-storage/54023/2 "2021-01-27T09:05:50Z")

</div>

Depending on the run-time of the computation, I think it’s cleaner to distribute the item in `data` using a channel:

```julia
provider = Channel() do provider
    for x in data
        put!(provider, x)
    end
end

ntasks = Threads.nthreads() # or some other positive integer
@sync for _ in 1:ntasks
    buffer = zeros(UInt8, 10^6)
    @spawn for x in provider
        f!(x, buffer)
    end
end

```

This makes the locality of `buffer` very apparent.

If `provider` channel becomes a bottleneck, you can send a chunk rather than an item:

```julia
provider = Channel() do provider
    basesize = some number
    for xs in Iterator.partition(data, basesize)
        put!(provider, xs)
    end
end

```

with `for x in Iterators.flatten(provider)` in the child task.

Alternatively, you can avoid the bottleneck comes with a channel by using my package [FLoops.jl](https://github.com/JuliaFolds/FLoops.jl) and use an accumulator as a local storage… kind of:

```julia
basesize = some positive number
@floop ThreadedEx(basesize = basesize) for x in data
    y = Some(x)
    @reduce() do (buffer = zeros(UInt8, 10^6); y)
        if y isa Some
            f!(something(y), buffer)
        end
    end
end

```

It would call `zeros(UInt8, 10^6)` only up to `cld(length(data), basesize)` times. But this is super ugly/tricky and I should provide a better syntax…

> [@dmitrip](#):
>
> ```julia
> @sync for x in data
> # grab an id from the queue
> # this doesn't need to match the value returned by Threads.threadid()
> id = take!(available_ids)
> 
> Threads.@spawn begin
> 
> ```

Let me to nitpick that this would delay `@spawn` of new tasks until `available_ids` is “refilled”. It doesn’t matter if the task itself takes a long time compared to the over head of `take!` and `@spawn`, though. Also, I’d put buffers directly in the channel for simplicity, if I were to go with the strategy in the OP.

---

_[View the full topic](https://discourse.julialang.org/t/pattern-for-managing-thread-local-storage/54023)._
