Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@ import Base: @deprecate
(flag, stat) = Iprobe(src, tag, comm)
flag || return (false, nothing, nothing)
count = Get_count(stat, UInt8)
if isnothing(count)
# As in `recv`: counting in `UInt8` can only fail by overflowing the
# `Cint` that `MPI_Get_count` reports through.
error("`MPI.irecv`: the message is larger than $(typemax(Cint)) bytes, which `MPI_Get_count` cannot report")
end
buf = Array{UInt8}(undef, count)
stat = Recv!(buf, Get_source(stat), Get_tag(stat), comm)
(true, MPI.deserialize(buf), stat)
Expand Down
6 changes: 5 additions & 1 deletion src/group.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,18 @@ end

The rank of the process in the particular group.

Returns an integer in the range `0:MPI.Group_size()-1`.
Returns an integer in the range `0:MPI.Group_size()-1`, or `nothing` if the calling process
is not a member of `group`.

# External links
$(_doc_external("MPI_Group_rank"))
"""
function Group_rank(group::Group)
rank = Ref{Cint}()
API.MPI_Group_rank(group, rank)
# `MPI_UNDEFINED` is not a rank; return `nothing` rather than let the
# sentinel escape as an ordinary integer.
rank[] == API.MPI_UNDEFINED[] && return nothing
Int(rank[])
end

Expand Down
7 changes: 6 additions & 1 deletion src/nonblocking.jl
Original file line number Diff line number Diff line change
Expand Up @@ -415,14 +415,19 @@ end

The number of entries received. `T` should match the argument provided by the receive call that set the status variable.

If the number of entries received exceeds the limits of the count parameter, then it returns `MPI_UNDEFINED`.
Returns `nothing` if there is no meaningful count to report, which MPI signals as
`MPI_UNDEFINED`: either the number of entries received exceeds the limits of the count
parameter, or the number of bytes received is not a whole multiple of the size of `T`.

# External links
$(_doc_external("MPI_Get_count"))
"""
function Get_count(stat::Status, datatype::Datatype)
count = Ref{Cint}()
API.MPI_Get_count(Ref(stat), datatype, count)
# `MPI_UNDEFINED` is not a count; return `nothing` rather than let the
# sentinel escape as an ordinary integer (as `Waitany` and friends do).
count[] == API.MPI_UNDEFINED[] && return nothing
Int(count[])
end
Get_count(stat::Status, ::Type{T}) where {T} = Get_count(stat, Datatype(T))
Expand Down
6 changes: 6 additions & 0 deletions src/pointtopoint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ recv(comm::Comm, status=nothing; source::Integer=API.MPI_ANY_SOURCE[], tag::Inte
function recv(source::Integer, tag::Integer, comm::Comm, status::Union{Ref{Status}, Nothing})
msg, stat = Mprobe(comm, Status; source=source, tag=tag)
count = Get_count(stat, UInt8)
if isnothing(count)
# Counting in `UInt8` can only fail by overflowing the `Cint` that
# `MPI_Get_count` reports through; a byte count is necessarily a whole
# multiple of `sizeof(UInt8)`, so that cause cannot arise here.
error("`MPI.recv`: the message is larger than $(typemax(Cint)) bytes, which `MPI_Get_count` cannot report")
end
buf = Array{UInt8}(undef, count)
Mrecv!(buf, msg, status)
return MPI.deserialize(buf)
Expand Down
11 changes: 11 additions & 0 deletions test/test_group.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ grp5 = MPI.Group_excl(grp, Int32[0])
grp6 = MPI.Group_incl(grp, Int32[0])
@test MPI.Group_size(grp6) == 1

# `Group_rank` must report a non-member as `nothing` rather than let MPI's
# `MPI_UNDEFINED` sentinel escape as an ordinary integer. Rank 0 is not a
# member of grp5, and every other rank is not a member of grp6.
if MPI.Comm_rank(comm) == 0
@test MPI.Group_rank(grp5) === nothing
@test MPI.Group_rank(grp6) == 0
else
@test MPI.Group_rank(grp5) == MPI.Comm_rank(comm) - 1
@test MPI.Group_rank(grp6) === nothing
end

# Don't free the other groups
MPI.free(grp)

Expand Down
12 changes: 12 additions & 0 deletions test/test_sendrecv.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@ stats = MPI.Waitall(reqs, MPI.Status)
@test MPI.Get_count(stats[2], Float64) == N
@test recv_mesg == recv_mesg_expected

# `Get_count` must report `MPI_UNDEFINED` as `nothing` rather than let the
# sentinel escape as an ordinary integer. The message is N Float64s, and that
# many bytes is not a whole multiple of the size of a three-byte struct, so
# there is no integral count to report.
struct ThreeBytes
a::UInt8
b::UInt8
c::UInt8
end
@test sizeof(Float64) * N % sizeof(ThreeBytes) != 0 # the premise of the test below
@test MPI.Get_count(stats[2], ThreeBytes) === nothing

@test MPI.Testall(reqs)


Expand Down
Loading