ParallelUtilities.jl

ParallelUtilities.BroadcastFunction — Type
BroadcastFunction(f)

Construct a binary function that evaluates f.(x, y) given the arguments x and y.

Note

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
source
ParallelUtilities.BroadcastStack — Type
BroadcastStack(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.

Note

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
source
ParallelUtilities.Commutative — Type
Commutative

Declare a reduction operator to be commutative in its arguments. No check is performed to ascertain if the operator is indeed commutative.

source
ParallelUtilities.Flip — Type
Flip(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
source
ParallelUtilities.ProductSection — Type
ProductSection{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

source
ParallelUtilities.ProductSection — Method
ProductSection(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
source
ParallelUtilities.ProductSplit — Type
ProductSplit{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

source
ParallelUtilities.ProductSplit — Method
ProductSplit(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.

Note

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)
source
ParallelUtilities.broadcastinplace — Method
broadcastinplace(f, ::Val{N}) where {N}

Construct a binary operator that evaluates f.(x, y) and overwrites the Nth 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
source
ParallelUtilities.childindex — Method
childindex(ps::AbstractConstrainedProduct, ind)

Return a tuple containing the indices of the individual AbstractRanges corresponding to the element that is present at index ind in the outer product of the ranges.

Note

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

source
ParallelUtilities.childindexshifted — Method
childindexshifted(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

source
ParallelUtilities.dropleading — Method
dropleading(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)
source
ParallelUtilities.elementwisemax! — Function
elementwisemax!(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).

Note

The operator is assumed to be commutative.

source
ParallelUtilities.elementwisemin! — Function
elementwisemin!(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).

Note

The operator is assumed to be commutative.

source
ParallelUtilities.elementwiseproduct! — Function
elementwiseproduct!(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.

Note

The operator is assumed to be commutative.

source
ParallelUtilities.elementwisesum! — Function
elementwisesum!(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.

Note

The operator is assumed to be commutative.

source
ParallelUtilities.extrema_commonlastdim — Method
extrema_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)])
source
ParallelUtilities.extremadims — Method
extremadims(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))
source
ParallelUtilities.extremaelement — Method
extremaelement(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)
source
ParallelUtilities.indexinproduct — Method
indexinproduct(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
source
ParallelUtilities.localindex — Method
localindex(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
source
ParallelUtilities.masternodeindex — Method
masternodeindex(tree::SegmentedOrderedBinaryTree, p)

Given the top worker p on one node, compute the serial order of the host that it corresponds to.

source
ParallelUtilities.maximumelement — Method
maximumelement(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
source
ParallelUtilities.minimumelement — Method
minimumelement(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
source
ParallelUtilities.nelements — Method
nelements(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 AbstractUnitRanges.

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
source
ParallelUtilities.pmapreduce — Method
pmapreduce(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

source
ParallelUtilities.pmapreduce_productsplit — Method
pmapreduce_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 Tuples.

The keyword arguments reducekw are passed on to the reduction.

See also: pmapreduce

source
ParallelUtilities.procrange_recast — Method
procrange_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
source
ParallelUtilities.procrange_recast — Method
procrange_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
source
ParallelUtilities.whichproc — Method
whichproc(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
source
ParallelUtilities.whichproc_localindex — Method
whichproc_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)
source