Skip to content
Draft
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
1 change: 1 addition & 0 deletions docs/src/reference/pointtopoint.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ MPI.Sendrecv!
MPI.Isend
MPI.isend
MPI.Irecv!
MPI.Isendrecv!
```

### Completion
Expand Down
34 changes: 34 additions & 0 deletions src/pointtopoint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,40 @@ function Sendrecv!(sendbuf, dest::Integer, sendtag::Integer, recvbuf, source::In
return data, status[]
end

"""
req = Isendrecv!(sendbuf, recvbuf, comm::Comm[, req::AbstractRequest = Request()];
dest::Integer, sendtag::Integer=0, source::Integer=MPI.ANY_SOURCE, recvtag::Integer=MPI.ANY_TAG)

Starts a nonblocking combined send-receive over the MPI communicator `comm`. Sends `sendbuf` to the
MPI rank `dest` using message tag `sendtag`, and receive from MPI rank `source` into the buffer `recvbuf`
using message tag `recvtag`.

`sendbuf` can be a [`Buffer`](@ref), or any object for which `Buffer(sendbuf)` is defined (similarly for `recvbuf`).

Returns an [`AbstractRequest`](@ref) for the combined non-blocking operation.

# External links
$(_doc_external("MPI_Isendrecv"))
"""
Isendrecv!(sendbuf, recvbuf, comm::Comm, req::AbstractRequest=Request(); dest::Integer, sendtag::Integer=0, source::Integer=API.MPI_ANY_SOURCE[], recvtag::Integer=API.MPI_ANY_TAG[]) =
Isendrecv!(sendbuf, dest, sendtag, recvbuf, source, recvtag, comm, req)

function Isendrecv!(sendbuf::Buffer, dest::Integer, sendtag::Integer,
recvbuf::Buffer, source::Integer, recvtag::Integer,
comm::Comm, req::AbstractRequest=Request())
@assert isnull(req)
# int MPI_Isendrecv(const void* sendbuf, int sendcount, MPI_Datatype sendtype, int dest, int sendtag
# const void* recvbuf, int recvcount, MPI_Datatype recvtype, int source, int recvtag,
# MPI_Comm comm, MPI_Request *request)
API.MPI_Isendrecv(sendbuf.data, sendbuf.count, sendbuf.datatype, dest, sendtag,
recvbuf.data, recvbuf.count, recvbuf.datatype, source, recvtag,
comm, req)
setbuffer!(req, (sendbuf, recvbuf))
return req
end
Isendrecv!(sendbuf, dest::Integer, sendtag::Integer, recvbuf, source::Integer, recvtag::Integer, comm::Comm, req::AbstractRequest=Request()) =
Isendrecv!(Buffer(sendbuf), dest, sendtag, Buffer(recvbuf), source, recvtag, comm, req)

# persistent requests
"""
Send_init(buf, comm::MPI.Comm[, req::AbstractRequest = Request()];
Expand Down
39 changes: 39 additions & 0 deletions test/test_isendrecv.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
include("common.jl")

MPI.Init()

# initialise communicator variables
comm = MPI.COMM_WORLD
comm_rank = MPI.Comm_rank(comm)
comm_size = MPI.Comm_size(comm)

# cartesian comunicator topology
comm_cart = MPI.Cart_create(comm, (comm_size,); periodic=(true,), reorder=false)
src_rank, dest_rank = MPI.Cart_shift(comm_cart, 0, -1)

# construct buffers
sendbuf = Float64[comm_rank, comm_rank, comm_rank]
recvbuf = Float64[ -1, -1, -1]

# send entire buffer
req = MPI.Isendrecv!(sendbuf, recvbuf, comm_cart;
dest=dest_rank, sendtag=10, source=src_rank, recvtag=10)

@test req isa MPI.Request
@test !isnothing(req.buffer)

status = MPI.Wait(req, MPI.Status)

# ! doesn't work with MPICH backend
@test_broken MPI.Get_source(status) == src_rank
@test_broken MPI.Get_tag(status) == 10
@test recvbuf == [((comm_rank+1) % comm_size) for _ in 1:length(recvbuf)]

# compare to blocking Sendrecv!
a = Float64[comm_rank, comm_rank, comm_rank]
b = Float64[ -1, -1, -1]
MPI.Sendrecv!(a, b, comm_cart;
dest=dest_rank, sendtag=11, source=src_rank, recvtag=11)
@test b == recvbuf

MPI.Finalize()
Loading