From dfca21ed6774913e9f2895c3827157fe88101997 Mon Sep 17 00:00:00 2001 From: Moelf Date: Wed, 31 May 2023 13:50:17 -0400 Subject: [PATCH 1/3] change default threading scheduler to :static --- base/threadingconstructs.jl | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index 714a7054313d0..79120e3e4b440 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -185,11 +185,11 @@ function _threadsfor(iter, lbody, schedule) end end end - if $(schedule === :dynamic || schedule === :default) + if $(schedule === :dynamic) threading_run(threadsfor_fun, false) elseif ccall(:jl_in_threaded_region, Cint, ()) != 0 # :static error("`@threads :static` cannot be used concurrently or nested") - else # :static + elseif $(schedule === :static || schedule === :default) # :static threading_run(threadsfor_fun, true) end nothing @@ -234,12 +234,12 @@ For example, the above conditions imply that: ## Schedulers Without the scheduler argument, the exact scheduling is unspecified and varies across Julia -releases. Currently, `:dynamic` is used when the scheduler is not specified. +releases. Currently, `:static` is used when the scheduler is not specified. !!! compat "Julia 1.5" The `schedule` argument is available as of Julia 1.5. -### `:dynamic` (default) +### `:dynamic` `:dynamic` scheduler executes iterations dynamically to available worker threads. Current implementation assumes that the workload for each iteration is uniform. However, this @@ -256,9 +256,15 @@ smaller than the cost of spawning and synchronizing a task (typically less than microseconds). !!! compat "Julia 1.8" - The `:dynamic` option for the `schedule` argument is available and the default as of Julia 1.8. + The `:dynamic` option for the `schedule` argument is available as of Julia 1.8. -### `:static` +!!! warning + If your code rely on indexing buffer with [`Threads.threadid()`](@ref), you should + use `:static` shcedule. For example, the now-discouraged pattern from + [1.3 release blog post](https://julialang.org/blog/2019/07/multithreading/#thread-local_state) + Specifically, the use of `temps[Threads.threadid()]` is incorrect when using dynamic scheduler. + +### `:static` (default) `:static` scheduler creates one task per thread and divides the iterations equally among them, assigning each task specifically to each thread. In particular, the value of @@ -267,10 +273,11 @@ Specifying `:static` is an error if used from inside another `@threads` loop or thread other than 1. !!! note - `:static` scheduling exists for supporting transition of code written before Julia 1.3. + `:static` scheduling exists for supporting transition of code written earlier Julia. In newly written library functions, `:static` scheduling is discouraged because the functions using this option cannot be called from arbitrary worker threads. + ## Example To illustrate of the different scheduling strategies, consider the following function From 5ff803847d8bb2b3a4fd366f10b1f5f4d3734898 Mon Sep 17 00:00:00 2001 From: Moelf Date: Wed, 31 May 2023 15:52:49 -0400 Subject: [PATCH 2/3] fix whitespace --- base/threadingconstructs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index 79120e3e4b440..ff290be6179de 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -260,7 +260,7 @@ microseconds). !!! warning If your code rely on indexing buffer with [`Threads.threadid()`](@ref), you should - use `:static` shcedule. For example, the now-discouraged pattern from + use `:static` shcedule. For example, the now-discouraged pattern from [1.3 release blog post](https://julialang.org/blog/2019/07/multithreading/#thread-local_state) Specifically, the use of `temps[Threads.threadid()]` is incorrect when using dynamic scheduler. From e98626b02cebde866c9f22a955941a0cd65d2c43 Mon Sep 17 00:00:00 2001 From: Jerry Ling Date: Thu, 1 Jun 2023 11:18:27 -0400 Subject: [PATCH 3/3] fix test --- test/threads_exec.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/threads_exec.jl b/test/threads_exec.jl index 9c7c524febeff..b037b9021bb80 100644 --- a/test/threads_exec.jl +++ b/test/threads_exec.jl @@ -566,8 +566,8 @@ test_load_and_lookup_18020(10000) # This may not be efficient/fully supported but should work without crashing..... function test_nested_loops() a = zeros(Int, 100, 100) - @threads for i in 1:100 - @threads for j in 1:100 + @threads :dynamic for i in 1:100 + @threads :dynamic for j in 1:100 a[j, i] = i + j end end