It would of course be an option to put the whole loop in a function and just use an if else containing the for loops over the function but I would prefer the rest of the code as is.
Note that higher order functions and syntactic sugar like do
blocks make such solutions relatively straightforward to develop and easy to read:
You can start defining two higher-order functions that abstract away the for loop.
# This one is basically `Base.foreach`
function sequential_for(f, iterable)
for i in iterable
f(i)
end
end
# A thread-parallel version
function parallel_for(f, iterable)
Threads.@threads for i in iterable
f(i)
end
end
Then your function can dynamically decide which version of the for loop it wants to use:
function my_fun(n; parallel=false)
for_loop = parallel ? parallel_for : sequential_for
x = zeros(Int, n)
# The do syntax avoids having to either
# - define the loop body as a named function elsewhere, or
# - put an hard-to-read lambda directly as argument to `for_loop`
for_loop(1:n) do i
x[i] = Threads.threadid()
sleep(0.1) # Let's make sure we see the effect of parallelism :-)
end
return x
end
Example use:
julia> @time my_fun(10)
1.025307 seconds (299 allocations: 17.109 KiB)
10-element Array{Int64,1}:
1
1
1
1
1
1
1
1
1
1
julia> @time my_fun(10, parallel=true)
0.235430 seconds (18.44 k allocations: 979.714 KiB)
10-element Array{Int64,1}:
1
1
2
2
3
4
5
6
7
8
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…