Collective Communication

Image Source

Scatter

Rank 0 acts as a leader, creating a list and scattering it out to all ranks evenly

using MPI

MPI.Init()
comm = MPI.COMM_WORLD
rank = MPI.Comm_rank(comm)
size = MPI.Comm_size(comm)

send_buf = nothing
recv_buf = Vector{Float64}(undef, size)

if rank == 0
    send_buf = collect(1:size) .* 100
    print("Original array on rank 0:\n $(send_buf)\n")
end
    
recv_buf = MPI.Scatter(send_buf, Int, comm; root=0)
print("I got this on rank $(rank):\n $(recv_buf)\n")

If the preceding code is saved to a file Scatter1.jl, we can run

!~/.julia/bin/mpiexecjl --project=.. -np 2 julia Scatter1.jl
ERROR: 
Original array on rank 0:
 [100, 200]
ERROR: 
LoadError: 
LoadError: 
MethodError: MethodError: 
no method matching no method matching Scatter(Scatter(::::
Vector{Int64}, ::Type{Int64}, ::MPI.CommNothing, ::Type{Int64}, ::MPI.Comm; ; 
root=root=00))
Closest candidates are:
  Scatter(::Any, ::Type{T}, !Matched::Integer, !Matched::MPI.Comm) where T at ~/.julia/packages/MPI/08SPr/src/collective.jl:148 got unsupported keyword argument "root"
  Scatter(::Any, !Matched::Integer, !Matched::Integer, !Matched::MPI.Comm) at /usr/local/julia1.7.2/share/julia/base/deprecated.jl:70 got unsupported keyword argument "root"
Stacktrace:
 [1] top-level scope
Closest candidates are:
  Scatter(::Any, ::Type{T}, !Matched::Integer, !Matched::MPI.Comm) where T at ~/.julia/packages/MPI/08SPr/src/collective.jl:148 got unsupported keyword argument "root"
  Scatter(::Any, !Matched::Integer, !Matched::Integer, !Matched::MPI.Comm) at /usr/local/julia1.7.2/share/julia/base/deprecated.jl:70 got unsupported keyword argument "root"
Stacktrace:
 [1] top-level scope
   @ ~/work/hpc-book/hpc-book/src/   @ ~/work/hpc-book/hpc-book/src/
Scatter1.jl:17
in expression starting at /home/runner/work/hpc-book/hpc-book/src/Scatter1.jl:17
Scatter1.jl:17
in expression starting at /home/runner/work/hpc-book/hpc-book/src/Scatter1.jl:17
ERROR: 
failed process: Process(`/home/runner/.julia/artifacts/af2355b4e003d5800b907f71eaf64c62b6e365f1/bin/mpiexec -np 2 julia Scatter1.jl`, ProcessExited(1)) [1]

Stacktrace:
  [1] pipeline_error
    @ ./process.jl:531 [inlined]
  [2] run(::Cmd; wait::Bool)
    @ Base ./process.jl:446
  [3] run(::Cmd)
    @ Base process.jl:444
  [4] (::var"#1#2")(exe::Cmd)
    @ Main none:4
  [5] (::MPI.var"#10#11"{var"#1#2"})(cmd::String)
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
  [6] (::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String})()
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:49
  [7] withenv(::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String}, ::Pair{String, String}, ::Vararg{Pair{String, String}})
    @ Base env.jl:172
  [8] withenv_executable_wrapper(f::Function, executable_path::String, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:48
  [9] invokelatest(::Any, ::Any, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./essentials.jl:716
 [10] invokelatest(::Any, ::Any, ::Vararg{Any})
    @ Base ./essentials.jl:714
 [11] mpiexec(f::Function; adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [12] mpiexec(f::Function)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [13] mpiexec(fn::var"#1#2")
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
 [14] top-level scope
    @ none:4

Scatter!

using MPI

MPI.Init()
comm = MPI.COMM_WORLD
rank = MPI.Comm_rank(comm)
size = MPI.Comm_size(comm)

send_buf = nothing
recv_buf = Vector{Float64}(undef, size)

if rank == 0
    send_buf = rand(Float64, (size, size))
    print("Original array on rank 0:\n $(send_buf)\n")
end
    
MPI.Scatter!(send_buf, recv_buf, comm; root=0)
print("I got this array on $(rank):\n $(recv_buf)\n")

If the preceding code is saved to a file Scatter2.jl, we can run

!~/.julia/bin/mpiexecjl --project=.. -np 2 julia Scatter2.jl
ERROR: 
LoadError: Original array on rank 0:
 [0.7626199145855244 0.6818991425600491; 0.7914660525484276 0.7460579197627839]
ERROR: 
LoadError: 
MethodError: 
no method matching Scatter!(::
MethodError: 
no method matching Scatter!(::
Nothing, ::Vector{Float64}, ::MPI.Comm; 
root=0)
Closest candidates are:
  Scatter!(::Nothing, ::Any, !Matched::Integer, !Matched::MPI.Comm) at ~/.julia/packages/MPI/08SPr/src/collective.jl:132 got unsupported keyword argument "root"
  Scatter!(::Nothing, ::AbstractArray, !Matched::Integer, !Matched::Integer, !Matched::MPI.Comm) at /usr/local/julia1.7.2/share/julia/base/deprecated.jl:70 got unsupported keyword argument "root"
  Scatter!(::Any, ::AbstractArray, !Matched::Integer, !Matched::Integer, !Matched::MPI.Comm) at /usr/local/julia1.7.2/share/julia/base/deprecated.jl:70 got unsupported keyword argument "root"
  ...
Stacktrace:
 [1] top-level scope
Matrix{Float64}, ::Vector{Float64}, ::MPI.Comm; 
root=0)   @ ~/work/hpc-book/hpc-book/src/
Scatter2.jl:17
in expression starting at /home/runner/work/hpc-book/hpc-book/src/Scatter2.jl:17
ERROR: 
failed process: Process(`
/home/runner/.julia/artifacts/af2355b4e003d5800b907f71eaf64c62b6e365f1/bin/mpiexec -np 2 julia Scatter2.jl`, ProcessExited(1)) [1]

Stacktrace:
  [1] pipeline_error
    @ ./process.jl:531 [inlined]
  [2] run(::Cmd; wait::Bool)
    @ Base ./process.jl:446
  [3] run(::Cmd)
    @ Base process.jl:444
  [4] (::var"#1#2")(exe::Cmd)
    @ Main none:4
  [5] (::MPI.var"#10#11"{var"#1#2"})(cmd::String)
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
  [6] (::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String})()
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:49
  [7] withenv(::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String}, ::Pair{String, String}, ::Vararg{Pair{String, String}})
    @ Base env.jl:172
  [8] withenv_executable_wrapper(f::Function, executable_path::String, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:48
  [9] invokelatest(::Any, ::Any, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./essentials.jl:716
 [10] invokelatest(::Any, ::Any, ::Vararg{Any})
    @ Base ./essentials.jl:714
 [11] mpiexec(f::Function; adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [12] mpiexec(f::Function)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [13] mpiexec(fn::var"#1#2")
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
 [14] top-level scope
    @ none:4

Scatterv!

using MPI

MPI.Init()
comm = MPI.COMM_WORLD
rank = MPI.Comm_rank(comm)
size = MPI.Comm_size(comm)

send_buf = nothing

if rank == 0
    recv_buf = Vector{Float64}(undef, size-1)
    send_buf = rand(Float64, (size, size))
    print("Original array on rank 0:\n $(send_buf)\n")
else
    recv_buf = Vector{Float64}(undef, size+1)
end

lengths = [size-1, size+1]
offsets = [0, size-1]
    
MPI.Scatterv!(VBuffer(send_buf, lengths, offsets, MPI.DOUBLE), recv_buf, comm; root=0)
print("I got this array on $(rank):\n $(recv_buf)\n")

If the preceding code is saved to a file Scatter3.jl, we can run

!~/.julia/bin/mpiexecjl --project=.. -np 2 julia Scatter3.jl
ERROR: 
Original array on rank 0:
 [0.18319437110879566 0.4222002392843601; 0.06283817786540602 0.5032447939753978]
LoadError: 
ERROR: 
LoadError: 
MethodError: 
no method matching Scatterv!(::
MethodError: 
no method matching Scatterv!(
::
VBuffer{Nothing}, ::Vector{Float64}, ::MPI.Comm; 
root=0)
VBuffer{Matrix{Float64}}, ::Vector{Float64}, ::MPI.Comm
; root=0)
Closest candidates are:
  Scatterv!(::VBuffer, ::Any, !Matched::Integer, !Matched::MPI.Comm) at ~/.julia/packages/MPI/08SPr/src/collective.jl:194 got unsupported keyword argument "root"
  Scatterv!(::Any, ::AbstractArray, !Matched::Vector, !Matched::Integer, !Matched::MPI.Comm) at /usr/local/julia1.7.2/share/julia/base/deprecated.jl:70 got unsupported keyword argument "root"
  Scatterv!(::Any, ::Any, !Matched::Vector, !Matched::Integer, !Matched::MPI.Comm) at /usr/local/julia1.7.2/share/julia/base/deprecated.jl:70 got unsupported keyword argument "root"
  ...
Stacktrace:
 [1] top-level scope
   @ ~/work/hpc-book/hpc-book/src/
Scatter3.jl:22
in expression starting at /home/runner/work/hpc-book/hpc-book/src/Scatter3.jl:22
ERROR: 
failed process: Process(`
/home/runner/.julia/artifacts/af2355b4e003d5800b907f71eaf64c62b6e365f1/bin/mpiexec -np 2 julia Scatter3.jl`, ProcessExited(1)) [1]

Stacktrace:
  [1] pipeline_error
    @ ./process.jl:531 [inlined]
  [2] run(::Cmd; wait::Bool)
    @ Base ./process.jl:446
  [3] run(::Cmd)
    @ Base process.jl:444
  [4] (::var"#1#2")(exe::Cmd)
    @ Main none:4
  [5] (::MPI.var"#10#11"{var"#1#2"})(cmd::String)
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
  [6] (::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String})()
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:49
  [7] withenv(::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String}, ::Pair{String, String}, ::Vararg{Pair{String, String}})
    @ Base env.jl:172
  [8] withenv_executable_wrapper(f::Function, executable_path::String, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:48
  [9] invokelatest(::Any, ::Any, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./essentials.jl:716
 [10] invokelatest(::Any, ::Any, ::Vararg{Any})
    @ Base ./essentials.jl:714
 [11] mpiexec(f::Function; adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [12] mpiexec(f::Function)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [13] mpiexec(fn::var"#1#2")
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
 [14] top-level scope
    @ none:4

Gather

Gather is a command that collects results from all processes into a list.

using MPI

MPI.Init()
comm = MPI.COMM_WORLD
rank = MPI.Comm_rank(comm)
size = MPI.Comm_size(comm)

send_buf = nothing

if rank == 0
    send_buf = collect(1:size) .* 100
    print("Original array on rank 0:\n $(send_buf)\n" )
end
    
v = MPI.Scatter(send_buf, Int, comm; root=0)
print("I got this on $(rank):\n $(v)\n")

v = v * v

recv_buf = MPI.Gather(v, comm; root=0)
if rank == 0
    print("New array on rank 0:\n $(recv_buf)")
end

If the preceding code is saved to a file Gather.jl, we can run

!~/.julia/bin/mpiexecjl --project=.. -np 2 julia Gather.jl
ERROR: 
Original array on rank 0:
 [100, 200]
LoadError: 
ERROR: 
LoadError: 
MethodError: 
no method matching Scatter(
::
MethodError: 
no method matching Scatter(::
Nothing, ::Type{Int64}, ::MPI.Comm; root=0
)
Vector{Int64}, ::Type{Int64}, ::MPI.Comm; 
root=0)
Closest candidates are:
  Scatter(::Any, ::Type{T}, !Matched::Integer, !Matched::MPI.Comm) where T at ~/.julia/packages/MPI/08SPr/src/collective.jl:148 got unsupported keyword argument "root"
  Scatter(::Any, !Matched::Integer, !Matched::Integer, !Matched::MPI.Comm) at /usr/local/julia1.7.2/share/julia/base/deprecated.jl:70 got unsupported keyword argument "root"
Stacktrace:
 [1] top-level scope
   @ ~/work/hpc-book/hpc-book/src/
Gather.jl:16
in expression starting at /home/runner/work/hpc-book/hpc-book/src/Gather.jl:16
ERROR: 
failed process: Process(`/home/runner/.julia/artifacts/af2355b4e003d5800b907f71eaf64c62b6e365f1/bin/mpiexec -np 2 julia Gather.jl`, ProcessExited(1)) [1]

Stacktrace:
  [1] pipeline_error
    @ ./process.jl:531 [inlined]
  [2] run(::Cmd; wait::Bool)
    @ Base ./process.jl:446
  [3] run(::Cmd)
    @ Base process.jl:444
  [4] (::var"#1#2")(exe::Cmd)
    @ Main none:4
  [5] (::MPI.var"#10#11"{var"#1#2"})(cmd::String)
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
  [6] (::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String})()
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:49
  [7] withenv(::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String}, ::Pair{String, String}, ::Vararg{Pair{String, String}})
    @ Base env.jl:172
  [8] withenv_executable_wrapper(f::Function, executable_path::String, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ JLLWrappers 
~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:48
  [9] invokelatest(::Any, ::Any, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./essentials.jl:716
 [10] invokelatest(::Any, ::Any, ::Vararg{Any})
    @ Base ./essentials.jl:714
 [11] mpiexec(f::Function; adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [12] mpiexec(f::Function)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [13] mpiexec(fn::var"#1#2")
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
 [14] top-level scope
    @ none:4

See also Gather!, Gatherv!, and Allgather/Allgather!/Allgatherv!

Broadcast

bcast sends a single object to every process.

using MPI

MPI.Init()

comm = MPI.COMM_WORLD
rank = MPI.Comm_rank(comm)
size = MPI.Comm_size(comm)

send_buf = nothing

if rank == 0
    send_buf = "Hello from rank 0!\n"
end

recv_buf = MPI.bcast(send_buf, comm; root=0)
print("Rank $(rank) recieved this message:\n  $(recv_buf)\n")

If the preceding code is saved to a file broadcast.jl, we can run

!~/.julia/bin/mpiexecjl --project=.. -np 2 julia broadcast.jl
ERROR: ERROR: 
LoadError: LoadError: 
MethodError: MethodError: 
no method matching no method matching bcastbcast((::::
String, ::MPI.CommNothing, ::MPI.Comm; 
; rootroot==00))
Closest candidates are:
  bcast(::Any, !Matched::Integer, !Matched::MPI.Comm) at ~/.julia/packages/MPI/08SPr/src/collective.jl:71 got unsupported keyword argument "root"
Stacktrace:
 [1] top-level scope

Closest candidates are:
  bcast(::Any, !Matched::Integer, !Matched::MPI.Comm) at ~/.julia/packages/MPI/08SPr/src/collective.jl:71 got unsupported keyword argument "root"
Stacktrace:
 [1] top-level scope
   @ ~/work/hpc-book/hpc-book/src/   @ ~/work/hpc-book/hpc-book/src/
broadcast.jl:16
in expression starting at /home/runner/work/hpc-book/hpc-book/src/broadcast.jl:16
broadcast.jl:16
in expression starting at /home/runner/work/hpc-book/hpc-book/src/broadcast.jl:16
ERROR: 
failed process: Process(`
/home/runner/.julia/artifacts/af2355b4e003d5800b907f71eaf64c62b6e365f1/bin/mpiexec -np 2 julia broadcast.jl`, ProcessExited(1)) [1]

Stacktrace:
  [1] pipeline_error
    @ ./process.jl:531 [inlined]
  [2] run(::Cmd; wait::Bool)
    @ Base ./process.jl:446
  [3] run(::Cmd)
    @ Base process.jl:444
  [4] (::var"#1#2")(exe::Cmd)
    @ Main none:4
  [5] (::MPI.var"#10#11"{var"#1#2"})(cmd::String)
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
  [6] (::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String})()
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:49
  [7] withenv(::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String}, ::Pair{String, String}, ::Vararg{Pair{String, String}})
    @ Base env.jl:172
  [8] withenv_executable_wrapper(f::Function, executable_path::String, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:48
  [9] invokelatest(::Any, ::Any, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./essentials.jl:716
 [10] invokelatest(::Any, ::Any, ::Vararg{Any})
    @ Base ./essentials.jl:714
 [11] mpiexec(f::Function; adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [12] mpiexec(f::Function)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [13] mpiexec(fn::var"#1#2")
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
 [14] top-level scope
    @ none:4

See also Bcast!.

Reduce

Reduce performs a parallel reduction operation.

using MPI

MPI.Init()

comm = MPI.COMM_WORLD
rank = MPI.Comm_rank(comm)
size = MPI.Comm_size(comm)

v = collect(1:size)
print("Original array on rank $(rank):\n  $(v)\n")
    

recv_buf = MPI.Reduce(v, +, comm; root=0)

if rank == 0
    print("New array on rank 0:\n  $(recv_buf)\n")
    total_sum = sum(recv_buf)
    print("Total sum:\n  $(total_sum)")
end

If the preceding code is saved to a file Reduce1.jl, we can run

!~/.julia/bin/mpiexecjl --project=.. -np 2 julia Reduce1.jl
Original array on rank 1:
  [1, 2]
Original array on rank 0:
  [1, 2]
ERROR: ERROR: 
LoadError: LoadError: 
MethodError: 
MethodError: 
no method matching Reduce(
::no method matching Reduce(::
Vector{Int64}, ::typeof(+), ::MPI.Comm; Vector{Int64}, ::typeof(+), ::MPI.Commroot=; 
0)root=0)
Closest candidates are:
  Reduce(::AbstractArray, ::Any, !Matched::Integer, !Matched::MPI.Comm) at ~/.julia/packages/MPI/08SPr/src/collective.jl:615 got unsupported keyword argument "root"
  Reduce(::T, ::Any, !Matched::Integer, !Matched::MPI.Comm) where T at ~/.julia/packages/MPI/08SPr/src/collective.jl:622 got unsupported keyword argument "root"
Stacktrace:
 [1] top-level scope

Closest candidates are:
  Reduce(::AbstractArray, ::Any, !Matched::Integer, !Matched::MPI.Comm) at ~/.julia/packages/MPI/08SPr/src/collective.jl:615 got unsupported keyword argument "root"
  Reduce(::T, ::Any, !Matched::Integer, !Matched::MPI.Comm) where T at ~/.julia/packages/MPI/08SPr/src/collective.jl:622 got unsupported keyword argument "root"
Stacktrace:
 [1] top-level scope
   @ ~/work/hpc-book/hpc-book/src/
   @ ~/work/hpc-book/hpc-book/src/
Reduce1.jl:14
in expression starting at /home/runner/work/hpc-book/hpc-book/src/Reduce1.jl:14
ERROR: 
failed process: Process(`/home/runner/.julia/artifacts/af2355b4e003d5800b907f71eaf64c62b6e365f1/bin/mpiexec -np 2 julia Reduce1.jl`, ProcessExited(1)) [1]

Stacktrace:
  [1] pipeline_error
    @ ./process.jl:531 [inlined]
  [2] run(::Cmd; wait::Bool)
    @ Base ./process.jl:446
  [3] run(::Cmd)
    @ Base process.jl:444
  [4] (::var"#1#2")(exe::Cmd)
    @ Main none:4
  [5] (::MPI.var"#10#11"{var"#1#2"})(cmd::String)
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
  [6] (::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String})()
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:49
  [7] withenv(::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String}, ::Pair{String, String}, ::Vararg{Pair{String, String}})
    @ Base env.jl:172
  [8] withenv_executable_wrapper(f::Function, executable_path::String, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:48
  [9] invokelatest(::Any, ::Any, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./essentials.jl:716
 [10] invokelatest(::Any, ::Any, ::Vararg{Any})
    @ Base ./essentials.jl:714
 [11] mpiexec(f::Function; adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [12] mpiexec(f::Function)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [13] mpiexec(fn::var"#1#2")
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
 [14] top-level scope
    @ none:4

Custom reduction operations

using MPI
MPI.Init()

import Base.+

struct Point{T}
    x::T
    y::T
end

+(A::Point{T}, B::Point{T}) where T = Point{T}(A.x + B.x, A.y + B.y)


comm = MPI.COMM_WORLD
rank = MPI.Comm_rank(comm)

p = Point(rank, rank) 
print("Original Point on rank $(rank):\n  $(p)\n")
    

recv_buf = MPI.Reduce(p, +, comm; root=0)

if rank == 0
    print("\nNew Point on rank 0:\n  $(recv_buf)\n")
end

If the preceding code is saved to a file Reduce2.jl, we can run

!~/.julia/bin/mpiexecjl --project=.. -np 3 julia Reduce2.jl
Original Point on rank 0:
  Point{Int64}(0, 0)
Original Point on rank 2:
  Point{Int64}(2, 2)
Original Point on rank 1:
  Point{Int64}(1, 1)
ERROR: ERROR: 
ERROR: 
LoadError: 
LoadError: 
LoadError: 
MethodError: 
no method matching Reduce(
::
MethodError: 
MethodError: 
no method matching 
Reduce(no method matching Reduce(::
::
Point{Int64}, ::typeof(+), ::MPI.Comm; 
root=0)
Closest candidates are:
  Reduce(::T, ::Any, !Matched::Integer, !Matched::MPI.Comm) where T at ~/.julia/packages/MPI/08SPr/src/collective.jl:622 got unsupported keyword argument "root"
  Reduce(!Matched::AbstractArray, ::Any, !Matched::Integer, !Matched::MPI.Comm) at ~/.julia/packages/MPI/08SPr/src/collective.jl:615 got unsupported keyword argument "root"
Stacktrace:
 [1] top-level scope
Point{Int64}, ::typeof(+), ::MPI.Comm
; root=0)
Point   @ {Int64}, ::typeof(+), ::MPI.Comm~/work/hpc-book/hpc-book/src/; 
rootReduce2.jl:22
in expression starting at /home/runner/work/hpc-book/hpc-book/src/Reduce2.jl:22
=0ERROR: 
failed process: Process(`
/home/runner/.julia/artifacts/af2355b4e003d5800b907f71eaf64c62b6e365f1/bin/mpiexec -np 3 julia Reduce2.jl`, ProcessExited(1)) [1]

Stacktrace:
  [1] pipeline_error
    @ ./process.jl:531 [inlined]
  [2] run(::Cmd; wait::Bool)
    @ Base ./process.jl:446
  [3] run(::Cmd)
    @ Base process.jl:444
  [4] (::var"#1#2")(exe::Cmd)
    @ Main none:4
  [5] (::MPI.var"#10#11"{var"#1#2"})(cmd::String)
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
  [6] (::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String})()
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:49
  [7] withenv(::JLLWrappers.var"#2#3"{MPI.var"#10#11"{var"#1#2"}, String}, ::Pair{String, String}, ::Vararg{Pair{String, String}})
    @ Base env.jl:172
  [8] withenv_executable_wrapper(f::Function, executable_path::String, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ JLLWrappers ~/.julia/packages/JLLWrappers/QpMQW/src/runtime.jl:48
  [9] invokelatest(::Any, ::Any, ::Vararg{Any}; kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ Base ./essentials.jl:716
 [10] invokelatest(::Any, ::Any, ::Vararg{Any})
    @ Base ./essentials.jl:714
 [11] mpiexec(f::Function; adjust_PATH::Bool, adjust_LIBPATH::Bool)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [12] mpiexec(f::Function)
    @ MPICH_jll ~/.julia/packages/JLLWrappers/QpMQW/src/products/executable_generators.jl:21
 [13] mpiexec(fn::var"#1#2")
    @ MPI ~/.julia/packages/MPI/08SPr/src/environment.jl:25
 [14] top-level scope
    @ none:4

See also Reduce! and Allreduce/Allreduce!.