Skip to content

Commit b01a333

Browse files
IanButterworthtkf
authored andcommitted
Make @threads :dynamic default (JuliaLang#44136)
Co-authored-by: Takafumi Arakaki <[email protected]>
1 parent 3de59e7 commit b01a333

File tree

3 files changed

+17
-28
lines changed

3 files changed

+17
-28
lines changed

NEWS.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ Command-line option changes
7373
Multi-threading changes
7474
-----------------------
7575

76-
* A new `:dynamic` schedule option for `Threads.@threads` which is similar to the default behavior except iterations
77-
will be scheduled dynamically to available worker threads rather than pinned to each thread. This option is more
78-
composable with (possibly nested) `@spawn` and `@threads` loops ([#43919])
76+
* `Threads.@threads` now defaults to a new `:dynamic` schedule option which is similar to the previous behavior except
77+
that iterations will be scheduled dynamically to available worker threads rather than pinned to each thread. This
78+
behavior is more composable with (possibly nested) `@spawn` and `@threads` loops ([#43919], [#44136])
7979

8080
Build system changes
8181
--------------------

base/threadingconstructs.jl

+11-22
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,11 @@ function _threadsfor(iter, lbody, schedule)
8585
end
8686
end
8787
end
88-
if $(schedule === :dynamic)
88+
if $(schedule === :dynamic || schedule === :default)
8989
threading_run(threadsfor_fun, false)
90-
elseif ccall(:jl_in_threaded_region, Cint, ()) != 0
91-
$(if schedule === :static
92-
:(error("`@threads :static` cannot be used concurrently or nested"))
93-
else
94-
# only use threads when called from outside @threads
95-
:(threadsfor_fun(onethread = true))
96-
end)
97-
else
90+
elseif ccall(:jl_in_threaded_region, Cint, ()) != 0 # :static
91+
error("`@threads :static` cannot be used concurrently or nested")
92+
else # :static
9893
threading_run(threadsfor_fun, true)
9994
end
10095
nothing
@@ -126,21 +121,21 @@ For example, the above conditions imply that:
126121
- Communicating between iterations using blocking primitives like `Channel`s is incorrect.
127122
- Write only to locations not shared across iterations (unless a lock or atomic operation is used).
128123
129-
130124
Schedule options are:
131125
- `:static` creates one task per thread and divides the iterations equally among
132126
them, assigning each task specifically to each thread.
133127
Specifying `:static` is an error if used from inside another `@threads` loop
134128
or from a thread other than 1.
135-
- `:dynamic` will schedule iterations dynamically to available worker threads,
129+
- `:dynamic` (default) will schedule iterations dynamically to available worker threads,
136130
assuming that the workload for each iteration is uniform.
137131
138-
Without the scheduler argument, the exact scheduling is unspecified; i.e. it may be
139-
different across Julia releases. Currently, the behavior is dependent on the calling thread.
140-
The default is `:static` when called from thread 1. The loop will be executed without threading
141-
when called from other threads.
132+
Without the scheduler argument, the exact scheduling is unspecified and varies across Julia releases.
142133
143-
The default schedule (used when no `schedule` argument is present) is subject to change.
134+
!!! compat "Julia 1.5"
135+
The `schedule` argument is available as of Julia 1.5.
136+
137+
!!! compat "Julia 1.8"
138+
The `:dynamic` option for the `schedule` argument is available and the default as of Julia 1.8.
144139
145140
For example, an illustration of the different scheduling strategies where `busywait`
146141
is a non-yielding timed loop that runs for a number of seconds.
@@ -172,12 +167,6 @@ julia> @time begin
172167
The `:dynamic` example takes 2 seconds since one of the non-occupied threads is able
173168
to run two of the 1-second iterations to complete the for loop.
174169
175-
!!! compat "Julia 1.5"
176-
The `schedule` argument is available as of Julia 1.5.
177-
178-
!!! compat "Julia 1.8"
179-
The `:dynamic` option for the `schedule` argument is available as of Julia 1.8.
180-
181170
See also: [`@spawn`](@ref Threads.@spawn), [`nthreads()`](@ref Threads.nthreads),
182171
[`threadid()`](@ref Threads.threadid), `pmap` in [`Distributed`](@ref man-distributed),
183172
`BLAS.set_num_threads` in [`LinearAlgebra`](@ref man-linalg).

test/threads_exec.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ function test_thread_cfunction()
503503
@test cfs[2] == cf(fs[2])
504504
@test length(unique(cfs)) == 1000
505505
ok = zeros(Int, nthreads())
506-
@threads for i in 1:10000
506+
@threads :static for i in 1:10000
507507
i = mod1(i, 1000)
508508
fi = fs[i]
509509
cfi = cf(fi)
@@ -705,9 +705,9 @@ let ch = Channel{Char}(0), t
705705
@test String(collect(ch)) == "hello"
706706
end
707707

708-
# errors inside @threads
708+
# errors inside @threads :static
709709
function _atthreads_with_error(a, err)
710-
Threads.@threads for i in eachindex(a)
710+
Threads.@threads :static for i in eachindex(a)
711711
if err
712712
error("failed")
713713
end

0 commit comments

Comments
 (0)