diff --git a/docs/src/reference/onesided.md b/docs/src/reference/onesided.md index 2b3b45593..69092e54d 100644 --- a/docs/src/reference/onesided.md +++ b/docs/src/reference/onesided.md @@ -3,9 +3,13 @@ ```@docs MPI.Win_create MPI.Win_create_dynamic +MPI.Win_allocate MPI.Win_allocate_shared MPI.Win_shared_query MPI.Win_flush +MPI.Win_flush_local +MPI.Win_lock_all +MPI.Win_unlock_all MPI.Win_lock MPI.Win_unlock MPI.Get! diff --git a/src/onesided.jl b/src/onesided.jl index e2deb823d..7b0d4cb63 100644 --- a/src/onesided.jl +++ b/src/onesided.jl @@ -69,6 +69,42 @@ function Win_create(base::SubArray{T}, comm::Comm; infokws...) where T Win_create(base, sizeof(base), sizeof(T), comm; infokws...) end +""" + win, array = MPI.Win_allocate(Array{T}, dims, comm::Comm; infokws...) + +Create and allocate a window for objects of type `T` of dimension +`dims` (either an integer or tuple of integers), returning a `Win` and the +`Array{T}` attached to the local process. + +This is a collective call over `comm`, but `dims` can differ for each call (and +can be zero). + +If the underlying implementation supports MPI 4.1, +use [`MPI.Win_shared_query`](@ref) to obtain the `Array` attached to a different +process in the same shared memory space. + +`infokws` are info keys providing optimization hints. + +[`MPI.free`](@ref) should be called on the `Win` object once operations have +been completed. +""" +function Win_allocate(::Type{Ptr{T}}, len::Integer, comm::Comm; kwargs...) where T + win = Win() + out_baseptr = Ref{Ptr{T}}() + # int MPI_Win_allocate(MPI_Aint size, int disp_unit, MPI_Info info, + # MPI_Comm comm, void *baseptr, MPI_Win *win) + API.MPI_Win_allocate(len*sizeof(T), sizeof(T), Info(kwargs...), comm, out_baseptr, win) + finalizer(free, win) + return win, out_baseptr[] +end +function Win_allocate(::Type{Array{T}}, dims, comm::Comm; kwargs...) where T + win, ptr = Win_allocate(Ptr{T}, prod(dims), comm; kwargs...) + array = unsafe_wrap(Array, ptr, dims) + win.object = array + finalizer(free, win) + return win, array +end + """ win, array = MPI.Win_allocate_shared(Array{T}, dims, comm::Comm; infokws...) @@ -184,6 +220,18 @@ function Win_fence(win::Win; nostore=false, noput=false, noprecede=false, nosucc Win_fence(assert, win) end +""" + Win_flush_local(win::Win; rank) + +Completes locally all outstanding RMA operations initiated by the calling process to the +target rank on the specified window. + +# External links +$(_doc_external("MPI_Win_flush_local")) +""" +Win_flush_local(win::Win; rank) = Win_flush_local(rank, win) +Win_flush_local(rank::Integer, win::Win) = API.MPI_Win_flush_local(rank, win) + """ Win_flush(win::Win; rank) @@ -198,6 +246,41 @@ Win_flush(rank::Integer, win::Win) = API.MPI_Win_flush(rank, win) Win_sync(win::Win) = API.MPI_Win_sync(win) +""" + Win_lock_all(win::Win; nocheck=false) + +Starts an RMA access epoch. The window can be +accessed by RMA operations at all processes on `win` during that epoch. +This operation is equivalent to a call to Win_lock(shared) for all processes +associted with the window. + +If `nocheck=true`, no other process holds, or will attempt to acquire, a +conflicting lock, while the caller holds the window lock. This is useful when +mutual exclusion is achieved by other means, but the coherence operations that +may be attached to the lock and unlock calls are still required. + +# External links +$(_doc_external("MPI_Win_lock_all")) +""" +function Win_lock_all(win::Win; nocheck::Bool = false) + Win_lock_all(nocheck * API.MPI_MODE_NOCHECK[], win) +end +function Win_lock_all(assert::Integer, win::Win) + # int MPI_Win_lock_all(int assert, MPI_Win win) + API.MPI_Win_lock_all(assert, win) +end + +""" + Win_unlock_all(win::Win) + +Completes an RMA access epoch started by a call to [`Win_lock_all`](@ref). + +# External links +$(_doc_external("MPI_Win_unlock_all")) +""" +Win_unlock_all(win::Win) = Win_unlock_all(win) +Win_unlock_all(win::Win) = API.MPI_Win_unlock_all(win) + """ Win_lock(win::Win; rank::Integer, type=:exclusive/:shared, nocheck=false)