API
@floop
FLoops.@floop
— Macro@floop begin
s₁ = initialization of s₁
s₂ # pre-initialized variable
...
for x in xs, ...
...
end
end
@floop begin ... end
expects a (possibly empty) series of assignments or variable declaration (as in s₂
above) followed by a for
loop.
When there is no induction variables, begin ... end
can be omitted:
@floop for x in xs, ...
...
end
Use @reduce
for parallel execution:
@floop for x in xs, ...
...
@reduce ...
end
@floop
can also take an executor
argument (which should be an instance of executor such as SequentialEx
, ThreadedEx
and DistributedEx
) or a nothing
(indicating an appropriate parallel executor):
@floop executor for x in xs, ...
...
@reduce ...
end
See the module docstring of FLoops
for examples.
@reduce
FLoops.@reduce
— Macro@reduce() do (acc₁ [= init₁]; x₁), ..., (accₙ [= initₙ]; xₙ)
...
end
@reduce(acc₁ ⊗₁= x₁, ..., accₙ ⊗ₙ= xₙ)
@reduce(acc₁ .⊗₁= x₁, ..., accₙ .⊗ₙ= xₙ)
@reduce(acc₁ = ⊗₁(init₁, x₁), ..., accₙ = ⊗ₙ(initₙ, xₙ))
@reduce(acc₁ .= (⊗₁).(init₁, x₁), ..., accₙ = (⊗ₙ).(initₙ, xₙ))
Declare how accumulators are updated in the sequential basecase and how the resulting accumulators from two basecases are combined.
The arguments accᵢ
and xᵢ
must be symbols except for xᵢ
of the last three forms in which an expression can be used at xᵢ
.
In the first form,
function ((acc₁, acc₂, ..., accₙ), (x₁, x₂, ..., xₙ))
... # body of the `do` block
return (acc₁, acc₂, ..., accₙ)
end
should be an associative function.
In the last three forms, every binary operation ⊗ᵢ
should be an associative function.
If initᵢ
is specified, the tuple (init₁, init₂, ..., initₙ)
should be the identify of the related associative function. accᵢ = initᵢ
is evaluated for each basecase (each Task
) in the beginning.
Consider a loop with the following form
@floop for ...
# code computing (x₁, x₂, ..., xₙ)
@reduce() do (acc₁ = init₁; x₁), ..., (accₙ = initₙ; xₙ)
# code updating (acc₁, acc₂, ..., accₙ) using (x₁, x₂, ..., xₙ)
end
end
This is converted to
acc₁ = init₁
...
accₙ = initₙ
for ...
# code computing (x₁, x₂, ..., xₙ)
# code updating (acc₁, acc₂, ..., accₙ) using (x₁, x₂, ..., xₙ)
end
for computing (acc₁, acc₂, ..., accₙ)
of each basecase. The accumulators accᵢ
of two basecases are combined using "code updating (acc₁, acc₂, ..., accₙ)
using (x₁, x₂, ..., xₙ)
" where (x₁, x₂, ..., xₙ)
are replaced with (acc₁, acc₂, ..., accₙ)
of the next basecase. Note that "code computing (x₁, x₂, ..., xₙ)
" is not used for combining the basecases.
Examples
@reduce() do (vmax=-Inf; v), (imax=0; i)
if isless(vmax, v)
vmax = v
imax = i
end
end
@reduce(s += y, p *= y)
@reduce(xs = append!!(EmptyVector(), x), ys = append!!(EmptyVector(), y))
@init
FLoops.@init
— Macro@init begin
pv₁ = init₁
...
pvₙ = initₙ
end
Initialize private variables pvᵢ
with initializer expression initᵢ
for each task. This can be used for mutating objects in a data race-free manner.
SequentialEx
, ThreadedEx
and DistributedEx
executors
An executor controls how a given @floop
is executed. FLoops.jl re-exports SequentialEx
, ThreadedEx
and DistributedEx
executors from Transducers.jl.
See also:
@floop
tutorials on executors- Executor section in Transducers.jl's glossary.
Transducers.SequentialEx
Transducers.ThreadedEx
Transducers.DistributedEx
- How is a parallel
@floop
executed? What is the scheduling strategy?
FLoops.assistant
FLoops.assistant
— FunctionFLoops.assistant(mode::Symbol)
FLoops.assistant(enable::Bool)
Set assistant mode; i.e., what to do when FLoops.jl finds a problematic usage pattern.
Assistant modes:
:ignore
: do nothing:warn
: print warning once:warn_always
: print warning always:error
: throw an error
FLoops.assistant(false)
is equivalent to FLoops.assistant(:ignore)
and FLoops.assistant(true)
is equivalent to FLoops.assistant(:warn)
.