diff --git a/README.md b/README.md index c0329ed65..53164af3f 100644 --- a/README.md +++ b/README.md @@ -196,12 +196,16 @@ Julia Function (assuming `import MPI`) | Fortran Function `MPI.Abort` | [`MPI_Abort`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Abort.3.php) `MPI.Comm_dup` | [`MPI_Comm_dup`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Comm_dup.3.php) `MPI.Comm_free` | [`MPI_Comm_free`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Comm_free.3.php) + `MPI.Comm_get_parent` | [`MPI_Comm_get_parent`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Comm_get_parent.3.php) `MPI.Comm_rank` | [`MPI_Comm_rank`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Comm_rank.3.php) `MPI.Comm_size` | [`MPI_Comm_size`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Comm_size.3.php) + `MPI.Comm_spawn` | [`MPI_Comm_spawn`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Comm_spawn.3.php) `MPI.Finalize` | [`MPI_Finalize`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Finalize.3.php) `MPI.Finalized` | [`MPI_Finalized`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Finalized.3.php) + `MPI.Get_address` | [`MPI_Get_address`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Get_address.3.php) `MPI.Init` | [`MPI_Init`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Init.3.php) `MPI.Initialized` | [`MPI_Initialized`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Initialized.3.php) + `MPI.Intercomm_merge` | [`MPI_Intercomm_merge`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Intercomm_merge.3.php) `MPI.mpitype` | [`MPI_Type_create_struct`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Type_create_struct.3.php) and [`MPI_Type_commit`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Type_commit.3.php) (see: [mpitype note](#mpitypenote)) mpitype note: This is not strictly a wrapper for @@ -246,7 +250,22 @@ Julia Function (assuming `import MPI`) | Fortran Function `MPI.Scatter` | [`MPI_Scatter`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Scatter.3.php) `MPI.Scatterv` | [`MPI_Scatterv`](https://www.open-mpi.org/doc/v1.10/man3/MPI_Scatterv.3.php) - +#### One-sided communication +Julia Function (assuming `import MPI`) | Fortran Function +---------------------------------------|-------------------------------------------------------- + `MPI.Win_create` | [`MPI_Win_create`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Win_create.3.php) + `MPI.Win_create_dynamic` | [`MPI_Win_create_dynamic`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Win_create_dynamic.3.php) + `MPI.Win_attach` | [`MPI_Win_attach`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Win_attach.3.php) + `MPI.Win_detach` | [`MPI_Win_detach`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Win_detach.3.php) + `MPI.Win_fence` | [`MPI_Win_fence`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Win_fence.3.php) + `MPI.Win_flush` | [`MPI_Win_flush`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Win_flush.3.php) + `MPI.Win_free` | [`MPI_Win_free`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Win_free.3.php) + `MPI.Win_sync` | [`MPI_Win_sync`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Win_sync.3.php) + `MPI.Win_lock` | [`MPI_Win_lock`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Win_lock.3.php) + `MPI.Win_unlock` | [`MPI_Win_unlock`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Win_unlock.3.php) + `MPI.Get` | [`MPI_Get`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Get.3.php) + `MPI.Put` | [`MPI_Put`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Put.3.php) + `MPI.Fetch_and_op` | [`MPI_Fetch_and_op`](https://www.open-mpi.org/doc/v3.0/man3/MPI_Fetch_and_op.3.php) [Julia]: http://julialang.org/ [MPI]: http://www.mpi-forum.org/ diff --git a/REQUIRE b/REQUIRE index 4a9d26ae1..9c1a0cccb 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,3 +1,3 @@ julia 0.6 BinDeps -Compat 0.9.5 +Compat 0.42 diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index 2c7c5bc48..ca13aa3d8 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -38,16 +38,20 @@ FortranCInterface_HEADER(jlmpi_f2c.h MACRO_NAMESPACE "JLMPI_" SYMBOLS MPI_CANCEL MPI_COMM_DUP MPI_COMM_FREE + MPI_COMM_GET_PARENT MPI_COMM_RANK MPI_COMM_SIZE MPI_COMM_SPLIT MPI_COMM_SPLIT_TYPE MPI_EXSCAN + MPI_FETCH_AND_OP MPI_FINALIZE MPI_FINALIZED MPI_GATHER MPI_GATHER MPI_GATHERV + MPI_GET + MPI_GET_ADDRESS MPI_GET_COUNT MPI_GET_PROCESSOR_NAME MPI_INFO_CREATE @@ -58,6 +62,7 @@ FortranCInterface_HEADER(jlmpi_f2c.h MACRO_NAMESPACE "JLMPI_" SYMBOLS MPI_INFO_SET MPI_INIT MPI_INITIALIZED + MPI_INTERCOMM_MERGE MPI_IPROBE MPI_IRECV MPI_ISEND @@ -66,6 +71,7 @@ FortranCInterface_HEADER(jlmpi_f2c.h MACRO_NAMESPACE "JLMPI_" SYMBOLS MPI_PACK MPI_PACK_SIZE MPI_PROBE + MPI_PUT MPI_RECV MPI_RECV_INIT MPI_REDUCE @@ -88,6 +94,16 @@ FortranCInterface_HEADER(jlmpi_f2c.h MACRO_NAMESPACE "JLMPI_" SYMBOLS MPI_WAITALL MPI_WAITANY MPI_WAITSOME + MPI_WIN_ATTACH + MPI_WIN_CREATE + MPI_WIN_CREATE_DYNAMIC + MPI_WIN_DETACH + MPI_WIN_FENCE + MPI_WIN_FLUSH + MPI_WIN_FREE + MPI_WIN_LOCK + MPI_WIN_SYNC + MPI_WIN_UNLOCK MPI_WTICK MPI_WTIME ) diff --git a/deps/gen_constants.f90 b/deps/gen_constants.f90 index daf3da9da..68672d01d 100644 --- a/deps/gen_constants.f90 +++ b/deps/gen_constants.f90 @@ -40,6 +40,7 @@ program gen_constants call output("MPI_MAX ", MPI_MAX) call output("MPI_MAXLOC ", MPI_MAXLOC) call output("MPI_MIN ", MPI_MIN) + call output("MPI_NO_OP ", MPI_NO_OP) call output("MPI_MINLOC ", MPI_MINLOC) call output("MPI_PROD ", MPI_PROD) call output("MPI_REPLACE ", MPI_REPLACE) @@ -59,6 +60,9 @@ program gen_constants call output("MPI_TAG_UB ", MPI_TAG_UB) call output("MPI_UNDEFINED ", MPI_UNDEFINED) + call output("MPI_INFO_NULL ", MPI_INFO_NULL) + call output("MPI_LOCK_EXCLUSIVE", MPI_LOCK_EXCLUSIVE) + call output("MPI_LOCK_SHARED ", MPI_LOCK_SHARED) contains subroutine output(name, value) diff --git a/deps/gen_functions.c b/deps/gen_functions.c index c3ed335a0..fb4a45a0d 100644 --- a/deps/gen_functions.c +++ b/deps/gen_functions.c @@ -29,15 +29,19 @@ int main(int argc, char *argv[]) { printf(" :MPI_CANCEL => \"%s\",\n", STRING(MPI_CANCEL)); printf(" :MPI_COMM_DUP => \"%s\",\n", STRING(MPI_COMM_DUP)); printf(" :MPI_COMM_FREE => \"%s\",\n", STRING(MPI_COMM_FREE)); + printf(" :MPI_COMM_GET_PARENT => \"%s\",\n", STRING(MPI_COMM_GET_PARENT)); printf(" :MPI_COMM_RANK => \"%s\",\n", STRING(MPI_COMM_RANK)); printf(" :MPI_COMM_SIZE => \"%s\",\n", STRING(MPI_COMM_SIZE)); printf(" :MPI_COMM_SPLIT => \"%s\",\n", STRING(MPI_COMM_SPLIT)); printf(" :MPI_COMM_SPLIT_TYPE => \"%s\",\n", STRING(MPI_COMM_SPLIT_TYPE)); printf(" :MPI_EXSCAN => \"%s\",\n", STRING(MPI_EXSCAN)); + printf(" :MPI_FETCH_AND_OP => \"%s\",\n", STRING(MPI_FETCH_AND_OP)); printf(" :MPI_FINALIZE => \"%s\",\n", STRING(MPI_FINALIZE)); printf(" :MPI_FINALIZED => \"%s\",\n", STRING(MPI_FINALIZED)); printf(" :MPI_GATHER => \"%s\",\n", STRING(MPI_GATHER)); printf(" :MPI_GATHERV => \"%s\",\n", STRING(MPI_GATHERV)); + printf(" :MPI_GET => \"%s\",\n", STRING(MPI_GET)); + printf(" :MPI_GET_ADDRESS => \"%s\",\n", STRING(MPI_GET_ADDRESS)); printf(" :MPI_GET_COUNT => \"%s\",\n", STRING(MPI_GET_COUNT)); printf(" :MPI_GET_PROCESSOR_NAME => \"%s\",\n", STRING(MPI_GET_PROCESSOR_NAME)); @@ -49,6 +53,7 @@ int main(int argc, char *argv[]) { printf(" :MPI_INFO_SET => \"%s\",\n", STRING(MPI_INFO_SET)); printf(" :MPI_INIT => \"%s\",\n", STRING(MPI_INIT)); printf(" :MPI_INITIALIZED => \"%s\",\n", STRING(MPI_INITIALIZED)); + printf(" :MPI_INTERCOMM_MERGE => \"%s\",\n", STRING(MPI_INTERCOMM_MERGE)); printf(" :MPI_IPROBE => \"%s\",\n", STRING(MPI_IPROBE)); printf(" :MPI_IRECV => \"%s\",\n", STRING(MPI_IRECV)); printf(" :MPI_ISEND => \"%s\",\n", STRING(MPI_ISEND)); @@ -57,6 +62,7 @@ int main(int argc, char *argv[]) { printf(" :MPI_PACK => \"%s\",\n", STRING(MPI_PACK)); printf(" :MPI_PACK_SIZE => \"%s\",\n", STRING(MPI_PACK_SIZE)); printf(" :MPI_PROBE => \"%s\",\n", STRING(MPI_PROBE)); + printf(" :MPI_PUT => \"%s\",\n", STRING(MPI_PUT)); printf(" :MPI_RECV => \"%s\",\n", STRING(MPI_RECV)); printf(" :MPI_RECV_INIT => \"%s\",\n", STRING(MPI_RECV_INIT)); printf(" :MPI_REDUCE => \"%s\",\n", STRING(MPI_REDUCE)); @@ -77,6 +83,16 @@ int main(int argc, char *argv[]) { printf(" :MPI_WAITALL => \"%s\",\n", STRING(MPI_WAITALL)); printf(" :MPI_WAITANY => \"%s\",\n", STRING(MPI_WAITANY)); printf(" :MPI_WAITSOME => \"%s\",\n", STRING(MPI_WAITSOME)); + printf(" :MPI_WIN_ATTACH => \"%s\",\n", STRING(MPI_WIN_ATTACH)); + printf(" :MPI_WIN_CREATE => \"%s\",\n", STRING(MPI_WIN_CREATE)); + printf(" :MPI_WIN_CREATE_DYNAMIC => \"%s\",\n", STRING(MPI_WIN_CREATE_DYNAMIC)); + printf(" :MPI_WIN_DETACH => \"%s\",\n", STRING(MPI_WIN_DETACH)); + printf(" :MPI_WIN_FENCE => \"%s\",\n", STRING(MPI_WIN_FENCE)); + printf(" :MPI_WIN_FLUSH => \"%s\",\n", STRING(MPI_WIN_FLUSH)); + printf(" :MPI_WIN_FREE => \"%s\",\n", STRING(MPI_WIN_FREE)); + printf(" :MPI_WIN_LOCK => \"%s\",\n", STRING(MPI_WIN_LOCK)); + printf(" :MPI_WIN_SYNC => \"%s\",\n", STRING(MPI_WIN_SYNC)); + printf(" :MPI_WIN_UNLOCK => \"%s\",\n", STRING(MPI_WIN_UNLOCK)); printf(" :MPI_WTICK => \"%s\",\n", STRING(MPI_WTICK)); printf(" :MPI_WTIME => \"%s\",\n", STRING(MPI_WTIME)); printf(" :MPI_TYPE_CREATE_STRUCT => \"%s\",\n", @@ -86,6 +102,8 @@ int main(int argc, char *argv[]) { printf(")\n"); printf("\n"); printf("primitive type CComm %d end\n", (int)(sizeof(MPI_Comm) * 8)); + printf("primitive type CInfo %d end\n", (int)(sizeof(MPI_Info) * 8)); + printf("primitive type CWin %d end\n", (int)(sizeof(MPI_Win) * 8)); return 0; } diff --git a/src/mpi-base.jl b/src/mpi-base.jl index 0ecd510e6..1c3532786 100644 --- a/src/mpi-base.jl +++ b/src/mpi-base.jl @@ -84,7 +84,9 @@ const LOR = Op(MPI_LOR) const LXOR = Op(MPI_LXOR) const MAX = Op(MPI_MAX) const MIN = Op(MPI_MIN) +const NO_OP = Op(MPI_NO_OP) const PROD = Op(MPI_PROD) +const REPLACE = Op(MPI_REPLACE) const SUM = Op(MPI_SUM) mutable struct Request @@ -95,7 +97,6 @@ const REQUEST_NULL = Request(MPI_REQUEST_NULL, nothing) mutable struct Info val::Cint - #val::Cint function Info() newinfo = Ref{Cint}() ccall(MPI_INFO_CREATE, Void, (Ptr{Cint}, Ptr{Cint}), newinfo, &0 ) @@ -105,8 +106,15 @@ mutable struct Info info.val = MPI_INFO_NULL ) ) info end + + function Info(val::Cint) + if val != MPI_INFO_NULL + error("Info can only be created using Info()") + end + return new(MPI_INFO_NULL) + end end -const INFO_NULL = MPI_INFO_NULL +const INFO_NULL = Info(MPI_INFO_NULL) # the info functions assume that Fortran hidden arguments are placed at the end of the argument list function Info_set(info::Info,key::AbstractString,value::AbstractString) @@ -149,6 +157,17 @@ Get_error(stat::Status) = Int(stat.val[MPI_ERROR]) Get_source(stat::Status) = Int(stat.val[MPI_SOURCE]) Get_tag(stat::Status) = Int(stat.val[MPI_TAG]) +mutable struct Win + val::Cint + Win() = new(0) +end + +struct LockType + val::Cint +end +const LOCK_EXCLUSIVE = LockType(MPI_LOCK_EXCLUSIVE) +const LOCK_SHARED = LockType(MPI_LOCK_SHARED) + const ANY_SOURCE = Int(MPI_ANY_SOURCE) const ANY_TAG = Int(MPI_ANY_TAG) const TAG_UB = Int(MPI_TAG_UB) @@ -814,6 +833,129 @@ function Exscan(object::T, op::Op, comm::Comm) where T Exscan(sendbuf,1,op,comm) end +function Win_create(base::Array{T}, info::Info, comm::Comm, win::Win) where T + out_win = Ref(win.val) + ccall(MPI_WIN_CREATE, Void, + (Ptr{T}, Ref{Cptrdiff_t}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}), + base, Cptrdiff_t(length(base)), sizeof(T), info.val, comm.val, out_win, 0) + win.val = out_win[] +end + +function Win_create_dynamic(info::Info, comm::Comm, win::Win) + out_win = Ref(win.val) + ccall(MPI_WIN_CREATE_DYNAMIC, Void, + (Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}), + info.val, comm.val, out_win, 0) + win.val = out_win[] +end + +function Win_attach(win::Win, base::Array{T}) where T + ccall(MPI_WIN_ATTACH, Void, + (Ref{Cint}, Ptr{T}, Ref{Cptrdiff_t}, Ref{Cint}), + win.val, base, Cptrdiff_t(sizeof(base)), 0) +end + +function Win_detach(win::Win, base::Array{T}) where T + ccall(MPI_WIN_DETACH, Void, + (Ref{Cint}, Ptr{T}, Ref{Cint}), + win.val, base, 0) +end + +function Win_fence(assert::Integer, win::Win) + ccall(MPI_WIN_FENCE, Void, (Ref{Cint}, Ref{Cint}, Ref{Cint}), assert, win.val, 0) +end + +function Win_flush(rank::Integer, win::Win) + ccall(MPI_WIN_FLUSH, Void, (Ref{Cint}, Ref{Cint}, Ref{Cint}), rank, win.val, 0) +end + +function Win_free(win::Win) + ccall(MPI_WIN_FREE, Void, (Ref{Cint}, Ref{Cint}), win.val, 0) +end + +function Win_sync(win::Win) + ccall(MPI_WIN_SYNC, Void, (Ref{Cint}, Ref{Cint}), win.val, 0) +end + +function Win_sync(win::CWin) + ccall(:MPI_Win_sync, Void, (CWin,), win) +end + +function Win_lock(lock_type::LockType, rank::Integer, assert::Integer, win::Win) + ccall(MPI_WIN_LOCK, Void, + (Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}), + lock_type.val, rank, assert, win.val, 0) +end + +function Win_unlock(rank::Integer, win::Win) + ccall(MPI_WIN_UNLOCK, Void, (Ref{Cint}, Ref{Cint}, Ref{Cint}), rank, win.val, 0) +end + +function Get(origin_buffer::MPIBuffertype{T}, count::Integer, target_rank::Integer, target_disp::Integer, win::Win) where T + ccall(MPI_GET, Void, + (Ptr{T}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cptrdiff_t}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}), + origin_buffer, count, mpitype(T), target_rank, Cptrdiff_t(target_disp), count, mpitype(T), win.val, 0) +end +function Get(origin_buffer::Array{T}, target_rank::Integer, win::Win) where T + count = length(origin_buffer) + Get(origin_buffer, count, target_rank, 0, win) +end +function Get(origin_value::Ref{T}, target_rank::Integer, win::Win) where T + Get(origin_value, 1, target_rank, 0, win) +end + +function Put(origin_buffer::MPIBuffertype{T}, count::Integer, target_rank::Integer, target_disp::Integer, win::Win) where T + ccall(MPI_PUT, Void, + (Ptr{T}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cptrdiff_t}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}), + origin_buffer, count, mpitype(T), target_rank, Cptrdiff_t(target_disp), count, mpitype(T), win.val, 0) +end +function Put(origin_buffer::Array{T}, target_rank::Integer, win::Win) where T + count = length(origin_buffer) + Put(origin_buffer, count, target_rank, 0, win) +end +function Put(origin_value::Ref{T}, target_rank::Integer, win::Win) where T + Put(origin_value, 1, target_rank, 0, win) +end + +function Fetch_and_op(sourceval::MPIBuffertype{T}, returnval::MPIBuffertype{T}, target_rank::Integer, target_disp::Integer, op::Op, win::Win) where T + ccall(MPI_FETCH_AND_OP, Void, + (Ptr{T}, Ptr{T}, Ref{Cint}, Ref{Cint}, Ref{Cptrdiff_t}, Ref{Cint}, Ref{Cint}, Ref{Cint}), + sourceval, returnval, mpitype(T), target_rank, Cptrdiff_t(target_disp), op.val, win.val, 0) +end + +function Fetch_and_op(sourceval::MPIBuffertype{T}, returnval::MPIBuffertype{T}, target_rank::Integer, target_disp::Integer, op::Op, win::CWin) where T + ccall(:MPI_Fetch_and_op, Void, + (Ptr{T}, Ptr{T}, Cint, Cint, Cptrdiff_t, Cint, CWin), + sourceval, returnval, mpitype(T), target_rank, target_disp, op.val, win) +end + +function Get_address(location::MPIBuffertype{T}) where T + addr = Ref{Cptrdiff_t}(0) + ccall(MPI_GET_ADDRESS, Void, (Ptr{T}, Ref{Cptrdiff_t}, Ref{Cint}), location, addr, 0) + #ccall(:MPI_Get_address, Int, (Ptr{Void}, Ref{Cptrdiff_t}), location, addr) + return addr[] +end + +function Comm_get_parent() + comm_id = Ref{Cint}() + ccall(MPI_COMM_GET_PARENT, Void, (Ref{Cint}, Ref{Cint}), comm_id, 0) + return Comm(comm_id[]) +end + +function Comm_spawn(command::String, argv::Vector{String}, nprocs::Integer, comm::Comm, errors = Vector{Cint}(nprocs)) + c_intercomm = Ref{CComm}() + ccall(:MPI_Comm_spawn, Void, + (Cstring, Ptr{Ptr{Cchar}}, Cint, CInfo, Cint, CComm, Ref{CComm}, Ptr{Cint}), + command, argv, nprocs, CInfo(INFO_NULL), 0, CComm(comm), c_intercomm, errors) + return Comm(c_intercomm[]) +end + +function Intercomm_merge(intercomm::Comm, flag::Bool) + comm_id = Ref{Cint}() + ccall(MPI_INTERCOMM_MERGE, Void, (Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}), intercomm.val, Cint(flag), comm_id, 0) + return Comm(comm_id[]) +end + # Conversion between C and Fortran Comm handles: if HAVE_MPI_COMM_C2F # use MPI_Comm_f2c and MPI_Comm_c2f @@ -821,11 +963,24 @@ if HAVE_MPI_COMM_C2F ccall(:MPI_Comm_f2c, CComm, (Cint,), comm.val) Base.convert(::Type{Comm}, ccomm::CComm) = Comm(ccall(:MPI_Comm_c2f, Cint, (CComm,), ccomm)) + # Assume info is treated the same way + Base.convert(::Type{CInfo}, info::Info) = + ccall(:MPI_Info_f2c, CInfo, (Cint,), info.val) + Base.convert(::Type{Info}, cinfo::CInfo) = + Info(ccall(:MPI_Info_c2f, Cint, (CInfo,), cinfo)) + Base.convert(::Type{CWin}, win::Win) = + ccall(:MPI_Win_f2c, CWin, (Cint,), win.val) + Base.convert(::Type{Win}, cwin::CWin) = + Win(ccall(:MPI_Win_c2f, Cint, (CWin,), cwin)) elseif sizeof(CComm) == sizeof(Cint) # in MPICH, both C and Fortran use identical Cint comm handles # and MPI_Comm_c2f is not provided. Base.convert(::Type{CComm}, comm::Comm) = reinterpret(CComm, comm.val) Base.convert(::Type{Comm}, ccomm::CComm) = Comm(reinterpret(Cint, ccomm)) + Base.convert(::Type{CInfo}, info::Info) = reinterpret(CInfo, info.val) + Base.convert(::Type{Info}, cinfo::CInfo) = Info(reinterpret(Cint, cinfo)) + Base.convert(::Type{CWin}, win::Win) = reinterpret(CWin, win.val) + Base.convert(::Type{Win}, cwin::CWin) = Win(reinterpret(Cint, cwin)) else warn("No MPI_Comm_c2f found - conversion to/from MPI.CComm will not work") end diff --git a/test/runtests.jl b/test/runtests.jl index c3305a85a..c504a0675 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -18,7 +18,7 @@ const coverage_opts = # Files to run without mpiexec juliafiles = ["test_cman_julia.jl"] # Files to run with mpiexec -n 1 -singlefiles = [] +singlefiles = ["test_spawn.jl"] function runtests() nprocs = clamp(Sys.CPU_CORES, 2, 4) diff --git a/test/spawned_worker.jl b/test/spawned_worker.jl new file mode 100644 index 000000000..dbbd45fdf --- /dev/null +++ b/test/spawned_worker.jl @@ -0,0 +1,21 @@ +using Base.Test +using MPI + +MPI.Init() + +parent_comm = MPI.Comm_get_parent() +world_comm = MPI.Intercomm_merge(parent_comm, true) +rank = MPI.Comm_rank(world_comm) + +@test rank != 0 + +size = MPI.Comm_size(world_comm) +rank = MPI.Comm_rank(world_comm) +root = 0 + +val = rank == root ? size : nothing +@test MPI.Reduce(1, +, root, world_comm) == val + +MPI.Comm_free(world_comm) +MPI.Comm_free(parent_comm) +MPI.Finalize() diff --git a/test/test_info.jl b/test/test_info.jl index a2df82b2a..1f74b06ee 100644 --- a/test/test_info.jl +++ b/test/test_info.jl @@ -12,6 +12,6 @@ MPI.Info_set(info, "bar", "evenfaster") MPI.Info_delete(info, "bar") @test MPI.Info_get(info, "bar" ) == "" finalize(info) -@test info.val == MPI.INFO_NULL +@test info.val == MPI.MPI_INFO_NULL MPI.Finalize() diff --git a/test/test_onesided.jl b/test/test_onesided.jl new file mode 100644 index 000000000..af17376b2 --- /dev/null +++ b/test/test_onesided.jl @@ -0,0 +1,84 @@ +using Base.Test +using MPI + +MPI.Init() + +comm = MPI.COMM_WORLD + +const rank = MPI.Comm_rank(comm) +const N = MPI.Comm_size(comm) + +win = MPI.Win() +buf = fill(Int(rank),N) +received = fill(-1,N) + +# Test Get using fence +MPI.Win_create(buf, MPI.INFO_NULL, comm, win) +MPI.Win_fence(0, win) +MPI.Get(received, (rank+1)%N, win) +MPI.Win_fence(0, win) + +@test received == fill(Int(rank+1)%N, size(received)) + +# Test locked window +if rank != 0 + MPI.Win_lock(MPI.LOCK_EXCLUSIVE, 0, 0, win) + received[1] = rank + MPI.Put(received, 1, 0, rank, win) + MPI.Win_unlock(0, win) +else + buf[1] = 0 +end + +MPI.Win_fence(0, win) + +if rank == 0 + @test buf == collect(0:N-1) +end + +MPI.Barrier(comm) +MPI.Win_free(win) +MPI.Barrier(comm) + +# Try a dynamic window +MPI.Win_create_dynamic(MPI.INFO_NULL, comm, win) +MPI.Win_attach(win, buf) + +address_win = MPI.Win() +address_buf = Vector{Cptrdiff_t}(1) +MPI.Win_create(address_buf, MPI.INFO_NULL, comm, address_win) + +# Address for dynamic window is global instead of relative to the start of the buffer, so we need to share it +MPI.Win_lock(MPI.LOCK_EXCLUSIVE, rank, 0, address_win) +address_buf[1] = MPI.Get_address(buf) +MPI.Win_unlock(rank, address_win) + +MPI.Barrier(comm) + +# Test atomic operation +if rank == 0 + received = Ref(0) + to_send = Ref(0) + for r in 0:N-1 + address = Ref{Cptrdiff_t}(0) + MPI.Win_lock(MPI.LOCK_EXCLUSIVE, r, 0, address_win) + MPI.Get(address, r, address_win) + MPI.Win_flush(r, address_win) + to_send[] = r+5 + MPI.Win_lock(MPI.LOCK_EXCLUSIVE, r, 0, win) + MPI.Fetch_and_op(to_send, received, r, address[]+r*sizeof(Int), MPI.REPLACE, win) + MPI.Win_flush(r, win) + @test received[] == r + MPI.Win_unlock(r, win) + MPI.Win_unlock(r, address_win) + end +end + +MPI.Barrier(comm) + +@test buf[rank+1] == rank+5 + +MPI.Barrier(comm) +MPI.Win_detach(win, buf) +MPI.Win_free(win) +MPI.Finalize() diff --git a/test/test_spawn.jl b/test/test_spawn.jl new file mode 100644 index 000000000..b2cf3a670 --- /dev/null +++ b/test/test_spawn.jl @@ -0,0 +1,24 @@ +using Base.Test +using MPI + +MPI.Init() + +const N = clamp(Sys.CPU_CORES, 2, 4) + +exename = joinpath(JULIA_HOME, Base.julia_exename()) +@test isfile(exename) +errors = Vector{Cint}(N-1) +intercomm = MPI.Comm_spawn(exename, ["spawned_worker.jl"], N-1, MPI.COMM_WORLD, errors) +@test errors == zeros(Cint,N-1) +world_comm = MPI.Intercomm_merge(intercomm, false) + +size = MPI.Comm_size(world_comm) +rank = MPI.Comm_rank(world_comm) +root = 0 + +val = rank == root ? size : nothing +@test MPI.Reduce(1, +, root, world_comm) == val + +MPI.Comm_free(world_comm) +MPI.Comm_free(intercomm) +MPI.Finalize()