ParallelUtilities.jl
ParallelUtilities.AbstractConstrainedProduct
— TypeAbstractConstrainedProduct{T, N, Q}
Supertype of ProductSplit
and ProductSection
.
ParallelUtilities.BroadcastFunction
— TypeBroadcastFunction(f)
Construct a binary function that evaluates f.(x, y)
given the arguments x
and y
.
The function BroadcastFunction(f)
is equivalent to Base.BroadcastFunction(f)
on Julia versions 1.6 and above.
Examples
julia> ParallelUtilities.BroadcastFunction(+)(ones(3), ones(3))
3-element Vector{Float64}:
2.0
2.0
2.0
ParallelUtilities.BroadcastStack
— TypeBroadcastStack(f, dims)(x::AbstractArray, y::AbstractArray)
Construct a binary function that stacks its arguments along dims
, with overlapping indices I
being replaced by f(x[I], y[I])
. The arguments x
and y
must both be n
-dimensional arrays that have identical axes along all dimensions aside from those specified by dims
. The axes of the result along each dimensions d
in dims
would be union(axes(x, d), axes(y, d))
. Along the other dimensions the result has the same axes as x
and y
.
If the resulting axes along the concatenated dimensions are not 1-based, one might require an offset array package such as OffsetArrays.jl
.
Examples
julia> A = ones(2)*2
2-element Vector{Float64}:
2.0
2.0
julia> B = ones(3)*3
3-element Vector{Float64}:
3.0
3.0
3.0
julia> ParallelUtilities.BroadcastStack(min, 1)(A, B)
3-element Vector{Float64}:
2.0
2.0
3.0
julia> A = ones(2,2)*2
2×2 Matrix{Float64}:
2.0 2.0
2.0 2.0
julia> B = ones(2,3)*3
2×3 Matrix{Float64}:
3.0 3.0 3.0
3.0 3.0 3.0
julia> ParallelUtilities.BroadcastStack(+, 2)(A, B)
2×3 Matrix{Float64}:
5.0 5.0 3.0
5.0 5.0 3.0
ParallelUtilities.Commutative
— TypeCommutative
Declare a reduction operator to be commutative in its arguments. No check is performed to ascertain if the operator is indeed commutative.
ParallelUtilities.Flip
— TypeFlip(f)
Flip the arguments of a binary function f
, so that Flip(f)(x, y) == f(y,x)
.
Examples
julia> flip1 = ParallelUtilities.Flip(vcat);
julia> flip1(2, 3)
2-element Vector{Int64}:
3
2
Two flips pop the original function back:
julia> flip2 = ParallelUtilities.Flip(flip1);
julia> flip2(2, 3)
2-element Vector{Int64}:
2
3
ParallelUtilities.ProductSection
— TypeProductSection{T, N, Q<:NTuple{N,AbstractRange}}
Iterator that loops over a specified section of the outer product of ranges in. If the ranges are strictly increasing, the iteration will be in reverse - lexicographic order. Given N
ranges, each element returned by the iterator will be a tuple of length N
with one element from each range.
See also: ProductSplit
ParallelUtilities.ProductSection
— MethodProductSection(iterators::Tuple{Vararg{AbstractRange}}, inds::AbstractUnitRange)
Construct a ProductSection
iterator that represents a 1D view of the outer product of the ranges provided in iterators
, with the range of indices in the view being specified by inds
.
Examples
julia> p = ParallelUtilities.ProductSection((1:3, 4:6), 5:8);
julia> collect(p)
4-element Vector{Tuple{Int64, Int64}}:
(2, 5)
(3, 5)
(1, 6)
(2, 6)
julia> collect(p) == collect(Iterators.product(1:3, 4:6))[5:8]
true
ParallelUtilities.ProductSplit
— TypeProductSplit{T, N, Q<:NTuple{N,AbstractRange}}
Iterator that loops over a section of the outer product of ranges. If the ranges are strictly increasing, the iteration is in reverse - lexicographic order. Given N
ranges, each element returned by the iterator will be a tuple of length N
with one element from each range.
See also: ProductSection
ParallelUtilities.ProductSplit
— MethodProductSplit(iterators::Tuple{Vararg{AbstractRange}}, np::Integer, p::Integer)
Construct a ProductSplit
iterator that represents the outer product of the iterators split over np
workers, with this instance reprsenting the values on the p
-th worker.
p
here refers to the rank of the worker, and is unrelated to the worker ID obtained by executing myid()
on that worker.
Examples
julia> ParallelUtilities.ProductSplit((1:2, 4:5), 2, 1) |> collect
2-element Vector{Tuple{Int64, Int64}}:
(1, 4)
(2, 4)
julia> ParallelUtilities.ProductSplit((1:2, 4:5), 2, 2) |> collect
2-element Vector{Tuple{Int64, Int64}}:
(1, 5)
(2, 5)
ParallelUtilities.broadcastinplace
— Methodbroadcastinplace(f, ::Val{N}) where {N}
Construct a binary operator that evaluates f.(x, y)
and overwrites the N
th argument with the result. For N == 1
this evaluates x .= f.(x, y)
, whereas for N == 2
this evaluates y .= f.(x, y)
.
Examples
julia> op = ParallelUtilities.broadcastinplace(+, Val(1));
julia> x = ones(3); y = ones(3);
julia> op(x, y)
3-element Vector{Float64}:
2.0
2.0
2.0
julia> x # overwritten
3-element Vector{Float64}:
2.0
2.0
2.0
ParallelUtilities.childindex
— Methodchildindex(ps::AbstractConstrainedProduct, ind)
Return a tuple containing the indices of the individual AbstractRange
s corresponding to the element that is present at index ind
in the outer product of the ranges.
The index ind
corresponds to the outer product of the ranges, and not to ps
.
Examples
julia> iters = (1:5, 2:4, 1:3);
julia> ps = ParallelUtilities.ProductSplit(iters, 7, 1);
julia> ind = 6;
julia> cinds = ParallelUtilities.childindex(ps, ind)
(1, 2, 1)
julia> v = collect(Iterators.product(iters...));
julia> getindex.(iters, cinds) == v[ind]
true
See also: childindexshifted
ParallelUtilities.childindexshifted
— Methodchildindexshifted(ps::AbstractConstrainedProduct, ind)
Return a tuple containing the indices in the individual iterators given an index of ps
.
If the iterators (r1, r2, ...)
are used to generate ps
, then return (i1, i2, ...)
such that ps[ind] == (r1[i1], r2[i2], ...)
.
Examples
julia> iters = (1:5, 2:4, 1:3);
julia> ps = ParallelUtilities.ProductSplit(iters, 7, 3);
julia> psind = 4;
julia> cinds = ParallelUtilities.childindexshifted(ps, psind)
(3, 1, 2)
julia> getindex.(iters, cinds) == ps[psind]
true
See also: childindex
ParallelUtilities.dropleading
— Methoddropleading(ps::AbstractConstrainedProduct{T, N, NTuple{N,AbstractUnitRange}}) where {T,N}
Return a ProductSection
leaving out the first iterator contained in ps
. The range of values of the remaining iterators in the resulting ProductSection
will be the same as in ps
.
Examples
julia> ps = ParallelUtilities.ProductSplit((1:5, 2:4, 1:3), 7, 3);
julia> collect(ps)
7-element Vector{Tuple{Int64, Int64, Int64}}:
(5, 4, 1)
(1, 2, 2)
(2, 2, 2)
(3, 2, 2)
(4, 2, 2)
(5, 2, 2)
(1, 3, 2)
julia> ParallelUtilities.dropleading(ps) |> collect
3-element Vector{Tuple{Int64, Int64}}:
(4, 1)
(2, 2)
(3, 2)
ParallelUtilities.elementwisemax!
— Functionelementwisemax!(x, y)
Binary reduction operator that performs an elementwise max
and stores the result inplace in x
. The value of x
is overwritten in the process.
Functionally elementwisemax!(x, y)
is equivalent to x .= max.(x, y)
.
The operator is assumed to be commutative.
ParallelUtilities.elementwisemin!
— Functionelementwisemin!(x, y)
Binary reduction operator that performs an elementwise min
and stores the result inplace in x
. The value of x
is overwritten in the process.
Functionally elementwisemin!(x, y)
is equivalent to x .= min.(x, y)
.
The operator is assumed to be commutative.
ParallelUtilities.elementwiseproduct!
— Functionelementwiseproduct!(x, y)
Binary reduction operator that performs an elementwise product and stores the result inplace in x
. The value of x
is overwritten in the process.
Functionally elementwiseproduct!(x, y)
is equivalent to x .= x .* y
.
The operator is assumed to be commutative.
ParallelUtilities.elementwisesum!
— Functionelementwisesum!(x, y)
Binary reduction operator that performs an elementwise product and stores the result inplace in x
. The value of x
is overwritten in the process.
Functionally elementwisesum!(x, y)
is equivalent to x .= x .+ y
.
The operator is assumed to be commutative.
ParallelUtilities.extrema_commonlastdim
— Methodextrema_commonlastdim(ps::AbstractConstrainedProduct{T, N, <:NTuple{N,AbstractUnitRange}}) where {T,N}
Return the reverse - lexicographic extrema of values taken from ranges contained in ps
, where the pairs of ranges are constructed by concatenating the ranges along each dimension with the last one.
For two ranges this simply returns ([first(ps)], [last(ps)])
.
Examples
julia> ps = ParallelUtilities.ProductSplit((1:3, 4:7, 2:7), 10, 2);
julia> collect(ps)
8-element Vector{Tuple{Int64, Int64, Int64}}:
(3, 6, 2)
(1, 7, 2)
(2, 7, 2)
(3, 7, 2)
(1, 4, 3)
(2, 4, 3)
(3, 4, 3)
(1, 5, 3)
julia> ParallelUtilities.extrema_commonlastdim(ps)
([(1, 2), (6, 2)], [(3, 3), (5, 3)])
ParallelUtilities.extremadims
— Methodextremadims(ps::AbstractConstrainedProduct)
Compute the extrema of the sections of all the ranges contained in ps
. Functionally this is equivalent to
map(i -> extrema(ps, dims = i), 1:_niterators(ps))
but it is implemented more efficiently.
Returns a Tuple
containing the (min, max)
pairs along each dimension, such that the i
-th index of the result contains the extrema
along the section of the i
-th range contained locally.
Examples
julia> ps = ParallelUtilities.ProductSplit((1:2, 4:5), 2, 1);
julia> collect(ps)
2-element Vector{Tuple{Int64, Int64}}:
(1, 4)
(2, 4)
julia> ParallelUtilities.extremadims(ps)
((1, 2), (4, 4))
ParallelUtilities.extremaelement
— Methodextremaelement(ps::AbstractConstrainedProduct; dims::Integer)
Compute the extrema
of the section of the range number dims
contained in ps
.
Examples
julia> ps = ParallelUtilities.ProductSplit((1:2, 4:5), 2, 1);
julia> collect(ps)
2-element Vector{Tuple{Int64, Int64}}:
(1, 4)
(2, 4)
julia> ParallelUtilities.extremaelement(ps, dims = 1)
(1, 2)
julia> ParallelUtilities.extremaelement(ps, dims = 2)
(4, 4)
ParallelUtilities.indexinproduct
— Methodindexinproduct(iterators::NTuple{N, AbstractRange}, val::NTuple{N, Any}) where {N}
Return the index of val
in the outer product of iterators
. Return nothing if val
is not present.
Examples
julia> iterators = (1:4, 1:3, 3:5);
julia> val = (2, 2, 4);
julia> ind = ParallelUtilities.indexinproduct(iterators, val)
18
julia> collect(Iterators.product(iterators...))[ind] == val
true
ParallelUtilities.localindex
— Methodlocalindex(ps::AbstractConstrainedProduct{T}, val::T) where {T}
Return the index of val
in ps
. Return nothing
if the value is not found.
Examples
julia> ps = ParallelUtilities.ProductSplit((1:3, 4:5:20), 3, 2);
julia> collect(ps)
4-element Vector{Tuple{Int64, Int64}}:
(2, 9)
(3, 9)
(1, 14)
(2, 14)
julia> ParallelUtilities.localindex(ps, (3, 9))
2
ParallelUtilities.masternodeindex
— Methodmasternodeindex(tree::SegmentedOrderedBinaryTree, p)
Given the top worker p
on one node, compute the serial order of the host that it corresponds to.
ParallelUtilities.maximumelement
— Methodmaximumelement(ps::AbstractConstrainedProduct; dims::Integer)
Compute the maximum value of the section of the range number dims
contained in ps
.
Examples
julia> ps = ParallelUtilities.ProductSplit((1:2, 4:5), 2, 1);
julia> collect(ps)
2-element Vector{Tuple{Int64, Int64}}:
(1, 4)
(2, 4)
julia> ParallelUtilities.maximumelement(ps, dims = 1)
2
julia> ParallelUtilities.maximumelement(ps, dims = 2)
4
ParallelUtilities.minimumelement
— Methodminimumelement(ps::AbstractConstrainedProduct; dims::Integer)
Compute the minimum value of the section of the range number dims
contained in ps
.
Examples
julia> ps = ParallelUtilities.ProductSplit((1:2, 4:5), 2, 1);
julia> collect(ps)
2-element Vector{Tuple{Int64, Int64}}:
(1, 4)
(2, 4)
julia> ParallelUtilities.minimumelement(ps, dims = 1)
1
julia> ParallelUtilities.minimumelement(ps, dims = 2)
4
ParallelUtilities.nelements
— Methodnelements(ps::AbstractConstrainedProduct{T, N, <:NTuple{N,AbstractUnitRange}}; dims::Integer) where {T,N}
Compute the number of unique values in the section of the dims
-th range contained in ps
.
The function is defined currently only for iterator products of AbstractUnitRange
s.
Examples
julia> ps = ParallelUtilities.ProductSplit((1:5, 2:4, 1:3), 7, 3);
julia> collect(ps)
7-element Vector{Tuple{Int64, Int64, Int64}}:
(5, 4, 1)
(1, 2, 2)
(2, 2, 2)
(3, 2, 2)
(4, 2, 2)
(5, 2, 2)
(1, 3, 2)
julia> ParallelUtilities.nelements(ps, dims = 1)
5
julia> ParallelUtilities.nelements(ps, dims = 2)
3
julia> ParallelUtilities.nelements(ps, dims = 3)
2
ParallelUtilities.pmapbatch
— Methodpmapbatch(f, [pool::AbstractWorkerPool], iterators...)
Carry out a pmap
with the iterators
divided evenly among the available workers.
See also: pmapreduce
ParallelUtilities.pmapbatch_productsplit
— Methodpmapbatch_productsplit(f, [pool::AbstractWorkerPool], iterators...)
Carry out a pmap
with the outer product of iterators
divided evenly among the available workers. The function f
must accept a collection of Tuple
s.
See also: pmapbatch
, pmapreduce_productsplit
ParallelUtilities.pmapreduce
— Methodpmapreduce(f, op, [pool::AbstractWorkerPool], iterators...; reducekw...)
Evaluate a parallel mapreduce
over the elements from iterators
. For multiple iterators, apply f
elementwise.
The keyword arguments reducekw
are passed on to the reduction.
See also: pmapreduce_productsplit
ParallelUtilities.pmapreduce_productsplit
— Methodpmapreduce_productsplit(f, op, [pool::AbstractWorkerPool], iterators...; reducekw...)
Evaluate a parallel mapreduce over the outer product of elements from iterators
. The product of iterators
is split over the workers available, and each worker is assigned a section of the product. The function f
should accept a single argument that is a collection of Tuple
s.
The keyword arguments reducekw
are passed on to the reduction.
See also: pmapreduce
ParallelUtilities.procrange_recast
— Methodprocrange_recast(ps::AbstractConstrainedProduct, np_new::Integer)
Return the range of processor ranks that would contain the values in ps
if the iterators used to construct ps
were split across np_new
processes.
Examples
julia> iters = (1:10, 4:6, 1:4);
julia> ps = ParallelUtilities.ProductSplit(iters, 5, 2); # split across 5 processes initially
julia> ParallelUtilities.procrange_recast(ps, 10) # If `iters` were spread across 10 processes
3:4
ParallelUtilities.procrange_recast
— Methodprocrange_recast(iterators::Tuple{Vararg{AbstractRange}}, ps, np_new::Integer)
Return the range of processor ranks that would contain the values in ps
if the outer produce of the ranges in iterators
is split across np_new
workers.
The values contained in ps
should be a subsection of the outer product of the ranges in iterators
.
Examples
julia> iters = (1:10, 4:6, 1:4);
julia> ps = ParallelUtilities.ProductSplit(iters, 5, 2);
julia> ParallelUtilities.procrange_recast(iters, ps, 10)
3:4
ParallelUtilities.whichproc
— Methodwhichproc(iterators::Tuple{Vararg{AbstractRange}}, val::Tuple, np::Integer)
Return the processor rank that will contain val
if the outer product of the ranges contained in iterators
is split evenly across np
processors.
Examples
julia> iters = (1:4, 2:3);
julia> np = 2;
julia> ParallelUtilities.ProductSplit(iters, np, 2) |> collect
4-element Vector{Tuple{Int64, Int64}}:
(1, 3)
(2, 3)
(3, 3)
(4, 3)
julia> ParallelUtilities.whichproc(iters, (2, 3), np)
2
ParallelUtilities.whichproc_localindex
— Methodwhichproc_localindex(iterators::Tuple{Vararg{AbstractRange}}, val::Tuple, np::Integer)
Return (rank, ind)
, where rank
is the rank of the worker that val
will reside on if the outer product of the ranges in iterators
is spread over np
workers, and ind
is the index of val
in the local section on that worker.
Examples
julia> iters = (1:4, 2:8);
julia> np = 10;
julia> ParallelUtilities.whichproc_localindex(iters, (2, 4), np)
(4, 1)
julia> ParallelUtilities.ProductSplit(iters, np, 4) |> collect
3-element Vector{Tuple{Int64, Int64}}:
(2, 4)
(3, 4)
(4, 4)