Translation Guide

This page tries to give a general overview of how to translate patterns written with the built-in tools of Base.Threads using the OhMyThreads.jl API. Note that this should be seen as a rough guide and (intentionally) isn't supposed to replace a systematic introduction into OhMyThreads.jl.

Basics

@threads

# Base.Threads
using Base.Threads: @threads

@threads for i in 1:10
    println(i)
end
# OhMyThreads
using OhMyThreads: @tasks

@tasks for i in 1:10
    println(i)
end

# or
using OhMyThreads: tforeach

tforeach(1:10) do i
    println(i)
end

:static scheduling

# Base.Threads
using Base.Threads: @threads

@threads :static for i in 1:10
    println(i)
end
# OhMyThreads
using OhMyThreads: @tasks

@tasks for i in 1:10
    @set scheduler=:static
    println(i)
end

# or
using OhMyThreads: tforeach

tforeach(1:10; scheduler=:static) do i
    println(i)
end

@spawn

# Base.Threads
using Base.Threads: @spawn

@sync for i in 1:10
    @spawn println(i)
end
# OhMyThreads
using OhMyThreads: @tasks

@tasks for i in 1:10
    @set chunking=false
    println(i)
end

# or
using OhMyThreads: tforeach

tforeach(1:10; chunking=false) do i
    println(i)
end

# or
using OhMyThreads: @spawn

@sync for i in 1:10
    @spawn println(i)
end

Reduction

No built-in feature in Base.Threads.

# Base.Threads: basic manual implementation
using Base.Threads: @spawn

data = rand(10)
chunks_itr = Iterators.partition(data, length(data) ÷ nthreads())
tasks = map(chunks_itr) do chunk
    @spawn reduce(+, chunk)
end
reduce(+, fetch.(tasks))
# OhMyThreads
using OhMyThreads: @tasks
data = rand(10)

@tasks for x in data
    @set reducer=+
end

# or
using OhMyThreads: treduce

treduce(+, data)

Mutation

Warning

Parallel mutation of non-local state, like writing to a shared array, can be the source of correctness errors (e.g. race conditions) and big performance issues (e.g. false sharing). You should carefully consider whether this is necessary or whether the use of thread-safe storage is the better option. We don't recommend using the examples in this section for anything serious!

# Base.Threads
using Base.Threads: @threads
data = rand(10)

@threads for i in eachindex(data)
    data[i] = calc(i)
end
# OhMyThreads
using OhMyThreads: @tasks
data = rand(10)

@tasks for i in eachindex(data)
    data[i] = calc(i)
end

# or
using OhMyThreads: tforeach

tforeach(eachindex(data)) do i
    data[i] = calc(i)
end

# or
using OhMyThreads: tmap!

tmap!(data, eachindex(data)) do i
    calc(i)
end

Parallel initialization

Warning

Parallel mutation of non-local state, like writing to a shared array, can be the source of correctness errors (e.g. race conditions) and big performance issues (e.g. false sharing). You should carefully consider whether this is necessary or whether the use of thread-safe storage is the better option. We don't recommend using the examples in this section for anything serious!

# Base.Threads
using Base.Threads: @threads

data = Vector{Float64}(undef, 10)
@threads for i in eachindex(data)
    data[i] = calc(i)
end
# OhMyThreads
using OhMyThreads: @tasks

data = @tasks for i in 1:10
    @set collect=true
    calc(i)
end

# or
using OhMyThreads: tmap

data = tmap(i->calc(i), 1:10)

# or
using OhMyThreads: tcollect

data = tcollect(calc(i) for i in 1:10)