Skip to content

Commit 1fd0fe8

Browse files
committed
add threads static to aid thread API evolution
1 parent 9010b7f commit 1fd0fe8

File tree

3 files changed

+41
-17
lines changed

3 files changed

+41
-17
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ Command-line option changes
9797

9898
Multi-threading changes
9999
-----------------------
100+
* `@threads` now allows an optional schedule argument. Use `@threads static ...` to
101+
ensure that the same schedule will be used as in past versions; the default schedule
102+
is likely to change in the future.
100103

101104

102105
Build system changes

base/threadingconstructs.jl

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -93,31 +93,42 @@ function _threadsfor(iter,lbody)
9393
end
9494

9595
"""
96-
Threads.@threads
96+
Threads.@threads [schedule] for ... end
9797
98-
A macro to parallelize a for-loop to run with multiple threads. This spawns [`nthreads()`](@ref)
99-
number of threads, splits the iteration space amongst them, and iterates in parallel.
100-
A barrier is placed at the end of the loop which waits for all the threads to finish
101-
execution, and the loop returns.
98+
A macro to parallelize a `for` loop to run with multiple threads. Splits the iteration
99+
space among multiple tasks and runs those tasks on threads according to a scheduling
100+
policy.
101+
A barrier is placed at the end of the loop which waits for all tasks to finish
102+
execution.
103+
104+
The `schedule` argument can be used to request a particular scheduling policy.
105+
The only currently supported value is `static`, which creates one task per thread
106+
and divides the iterations equally among them.
107+
The default schedule (used when no `schedule` argument is present) is subject to change.
108+
109+
!!! compat "Julia 1.5"
110+
The `schedule` argument is available as of Julia 1.5.
102111
"""
103112
macro threads(args...)
104113
na = length(args)
105-
if na != 1
114+
if na == 2
115+
sched, ex = args
116+
elseif na == 1
117+
sched = :static
118+
ex = args[1]
119+
else
106120
throw(ArgumentError("wrong number of arguments in @threads"))
107121
end
108-
ex = args[1]
109-
if !isa(ex, Expr)
110-
throw(ArgumentError("need an expression argument to @threads"))
122+
if !(isa(ex, Expr) && ex.head === :for)
123+
throw(ArgumentError("@threads requires a `for` loop expression"))
111124
end
112-
if ex.head === :for
113-
if ex.args[1] isa Expr && ex.args[1].head === :(=)
114-
return _threadsfor(ex.args[1], ex.args[2])
115-
else
116-
throw(ArgumentError("nested outer loops are not currently supported by @threads"))
117-
end
118-
else
119-
throw(ArgumentError("unrecognized argument to @threads"))
125+
if sched != :static
126+
throw(ArgumentError("unsupported schedule argument in @threads"))
127+
end
128+
if !(ex.args[1] isa Expr && ex.args[1].head === :(=))
129+
throw(ArgumentError("nested outer loops are not currently supported by @threads"))
120130
end
131+
return _threadsfor(ex.args[1], ex.args[2])
121132
end
122133

123134
"""

test/threads_exec.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,16 @@ let a = zeros(nthreads())
729729
@test a == [1:nthreads();]
730730
end
731731

732+
# static schedule
733+
function _atthreads_static_schedule()
734+
ids = zeros(Int, nthreads())
735+
Threads.@threads static for i = 1:nthreads()
736+
ids[i] = Threads.threadid()
737+
end
738+
return ids
739+
end
740+
@test _atthreads_static_schedule() == [1:nthreads();]
741+
732742
try
733743
@macroexpand @threads(for i = 1:10, j = 1:10; end)
734744
catch ex

0 commit comments

Comments
 (0)