Skip to content

Commit 130c580

Browse files
authored
Merge pull request #256 from gasagna/master
add type_create_subarray function
2 parents 56aa9b0 + 92f2b35 commit 130c580

File tree

4 files changed

+165
-22
lines changed

4 files changed

+165
-22
lines changed

deps/build.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,13 @@ MPI_constants = [
6868
# proc
6969
"MPI_PROC_NULL",
7070

71+
# memory layout
72+
"MPI_ORDER_C",
73+
"MPI_ORDER_FORTRAN",
74+
7175
# status
7276
"MPI_STATUS_SIZE", # size of Status array
77+
"MPI_STATUS_IGNORE",
7378
"MPI_SOURCE", # index in Status array
7479
"MPI_TAG", # index in Status array
7580
"MPI_ERROR", # index in Status array
@@ -159,6 +164,7 @@ MPI_functions = [
159164
"MPI_TESTSOME",
160165
"MPI_TYPE_CONTIGUOUS",
161166
"MPI_TYPE_CREATE_STRUCT",
167+
"MPI_TYPE_CREATE_SUBARRAY",
162168
"MPI_TYPE_COMMIT",
163169
"MPI_UNPACK",
164170
"MPI_WAIT",

src/mpi-base.jl

Lines changed: 111 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,21 @@ function Get_count(stat::Status, ::Type{T}) where T
482482
Int(count[])
483483
end
484484

485+
"""
486+
Send(buf::MPIBuffertype{T}, count::Integer, datatype::Cint, dest::Integer,
487+
tag::Integer, comm::Comm) where T
488+
489+
Complete a blocking send of `count` elements of type `datatype` from `buf` to MPI
490+
rank `dest` of communicator `comm` using the message tag `tag`
491+
"""
492+
function Send(buf::MPIBuffertype{T}, count::Integer, datatype::Cint, dest::Integer,
493+
tag::Integer, comm::Comm) where T
494+
ccall(MPI_SEND, Nothing,
495+
(Ptr{T}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint},
496+
Ref{Cint}),
497+
buf, count, datatype, dest, tag, comm.val, 0)
498+
end
499+
485500
"""
486501
Send(buf::MPIBuffertype{T}, count::Integer, dest::Integer, tag::Integer,
487502
comm::Comm) where T
@@ -491,10 +506,7 @@ of communicator `comm` using with the message tag `tag`
491506
"""
492507
function Send(buf::MPIBuffertype{T}, count::Integer, dest::Integer,
493508
tag::Integer, comm::Comm) where T
494-
ccall(MPI_SEND, Nothing,
495-
(Ptr{T}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint},
496-
Ref{Cint}),
497-
buf, count, mpitype(T), dest, tag, comm.val, 0)
509+
Send(buf, count, mpitype(T), dest, tag, comm)
498510
end
499511

500512
"""
@@ -540,6 +552,25 @@ function send(obj, dest::Integer, tag::Integer, comm::Comm)
540552
Send(buf, dest, tag, comm)
541553
end
542554

555+
"""
556+
Isend(buf::MPIBuffertype{T}, count::Integer, datatype::Cint, dest::Integer,
557+
tag::Integer, comm::Comm) where T
558+
559+
Starts a nonblocking send of `count` elements of type `datatype` from `buf` to
560+
MPI rank `dest` of communicator `comm` using with the message tag `tag`
561+
562+
Returns the commication `Request` for the nonblocking send.
563+
"""
564+
function Isend(buf::MPIBuffertype{T}, count::Integer, datatype::Cint,
565+
dest::Integer, tag::Integer, comm::Comm) where T
566+
rval = Ref{Cint}()
567+
ccall(MPI_ISEND, Nothing,
568+
(Ptr{T}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint},
569+
Ptr{Cint}, Ref{Cint}),
570+
buf, count, datatype, dest, tag, comm.val, rval, 0)
571+
return Request(rval[], buf)
572+
end
573+
543574
"""
544575
Isend(buf::MPIBuffertype{T}, count::Integer, dest::Integer, tag::Integer,
545576
comm::Comm) where T
@@ -551,12 +582,7 @@ Returns the commication `Request` for the nonblocking send.
551582
"""
552583
function Isend(buf::MPIBuffertype{T}, count::Integer,
553584
dest::Integer, tag::Integer, comm::Comm) where T
554-
rval = Ref{Cint}()
555-
ccall(MPI_ISEND, Nothing,
556-
(Ptr{T}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint},
557-
Ptr{Cint}, Ref{Cint}),
558-
buf, count, mpitype(T), dest, tag, comm.val, rval, 0)
559-
Request(rval[], buf)
585+
Isend(buf, count, mpitype(T), dest, tag, comm)
560586
end
561587

562588
"""
@@ -611,6 +637,25 @@ function isend(obj, dest::Integer, tag::Integer, comm::Comm)
611637
Isend(buf, dest, tag, comm)
612638
end
613639

640+
"""
641+
Recv!(buf::MPIBuffertype{T}, count::Integer, datatype::Cint, src::Integer,
642+
tag::Integer, comm::Comm) where T
643+
644+
Completes a blocking receive of up to `count` elements of type `datatype` into `buf`
645+
from MPI rank `src` of communicator `comm` using with the message tag `tag`
646+
647+
Returns the `Status` of the receive
648+
"""
649+
function Recv!(buf::MPIBuffertype{T}, count::Integer, datatype::Cint, src::Integer,
650+
tag::Integer, comm::Comm) where T
651+
stat = Status()
652+
ccall(MPI_RECV, Nothing,
653+
(Ptr{T}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint},
654+
Ptr{Cint}, Ref{Cint}),
655+
buf, count, datatype, src, tag, comm.val, stat.val, 0)
656+
return stat
657+
end
658+
614659
"""
615660
Recv!(buf::MPIBuffertype{T}, count::Integer, src::Integer, tag::Integer,
616661
comm::Comm) where T
@@ -622,12 +667,7 @@ Returns the `Status` of the receive
622667
"""
623668
function Recv!(buf::MPIBuffertype{T}, count::Integer, src::Integer,
624669
tag::Integer, comm::Comm) where T
625-
stat = Status()
626-
ccall(MPI_RECV, Nothing,
627-
(Ptr{T}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint},
628-
Ptr{Cint}, Ref{Cint}),
629-
buf, count, mpitype(T), src, tag, comm.val, stat.val, 0)
630-
stat
670+
Recv!(buf, count, mpitype(T), src, tag, comm)
631671
end
632672

633673

@@ -672,24 +712,38 @@ function recv(src::Integer, tag::Integer, comm::Comm)
672712
end
673713

674714
"""
675-
Irecv!(buf::MPIBuffertype{T}, count::Integer, src::Integer, tag::Integer,
715+
Irecv!(buf::MPIBuffertype{T}, count::Integer, datatype::Cint, src::Integer, tag::Integer,
676716
comm::Comm) where T
677717
678-
Starts a nonblocking receive of up to `count` elements into `buf` from MPI rank
679-
`src` of communicator `comm` using with the message tag `tag`
718+
Starts a nonblocking receive of up to `count` elements of type `datatype` into `buf`
719+
from MPI rank `src` of communicator `comm` using with the message tag `tag`
680720
681721
Returns the communication `Request` for the nonblocking receive.
682722
"""
683-
function Irecv!(buf::MPIBuffertype{T}, count::Integer,
684-
src::Integer, tag::Integer, comm::Comm) where T
723+
function Irecv!(buf::MPIBuffertype{T}, count::Integer, datatype::Cint,
724+
src::Integer, tag::Integer, comm::Comm) where T
685725
val = Ref{Cint}()
686726
ccall(MPI_IRECV, Nothing,
687727
(Ptr{T}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint}, Ref{Cint},
688728
Ptr{Cint}, Ref{Cint}),
689-
buf, count, mpitype(T), src, tag, comm.val, val, 0)
729+
buf, count, datatype, src, tag, comm.val, val, 0)
690730
Request(val[], buf)
691731
end
692732

733+
"""
734+
Irecv!(buf::MPIBuffertype{T}, count::Integer, src::Integer, tag::Integer,
735+
comm::Comm) where T
736+
737+
Starts a nonblocking receive of up to `count` elements into `buf`
738+
from MPI rank `src` of communicator `comm` using with the message tag `tag`
739+
740+
Returns the communication `Request` for the nonblocking receive.
741+
"""
742+
function Irecv!(buf::MPIBuffertype{T}, count::Integer,
743+
src::Integer, tag::Integer, comm::Comm) where T
744+
Irecv!(buf, count, mpitype(T), src, tag, comm)
745+
end
746+
693747
"""
694748
Irecv!(buf::Array{T}, src::Integer, tag::Integer, comm::Comm) where T
695749
@@ -1707,6 +1761,41 @@ function Type_Create_Struct(nfields::Integer, blocklengths::MPIBuffertype{Cint},
17071761
return newtype_ref[]
17081762
end
17091763

1764+
"""
1765+
Type_Create_Subarray(ndims::Integer, array_of_sizes::MPIBuffertype{Cint},
1766+
array_of_subsizes::MPIBuffertype{Cint},
1767+
array_of_starts::MPIBuffertype{Cint}, order::Integer, oldtype)
1768+
1769+
Creates a data type describing an `ndims`-dimensional subarray of size `array_of_subsizes`
1770+
of an `ndims-dimensional` array of size `array_of_sizes` and element type `oldtype`,
1771+
starting at the top-left location `array_of_starts`. The parameter `order` refers to
1772+
the memory layout of the parent array, and can be either `MPI_ORDER_C` or
1773+
`MPI_ORDER_FORTRAN`. Note that, like other MPI data types, the type returned by this
1774+
function should be committed with `MPI_Type_commit`.
1775+
"""
1776+
function Type_Create_Subarray(ndims::Integer,
1777+
array_of_sizes::MPIBuffertype{Cint},
1778+
array_of_subsizes::MPIBuffertype{Cint},
1779+
array_of_starts::MPIBuffertype{Cint},
1780+
order::Integer,
1781+
oldtype)
1782+
1783+
newtype_ref = Ref{Cint}()
1784+
flag = Ref{Cint}()
1785+
1786+
ccall(MPI_TYPE_CREATE_SUBARRAY, Nothing,
1787+
(Ref{Cint}, Ptr{Cint}, Ptr{Cint}, Ptr{Cint},
1788+
Ref{Cint}, Ref{Cint}, Ptr{Cint}, Ptr{Cint}),
1789+
ndims, array_of_sizes, array_of_subsizes, array_of_starts,
1790+
order, mpitype(oldtype), newtype_ref, flag)
1791+
1792+
if flag[] != 0
1793+
throw(ErrorException("MPI_Type_create_subarray returned non-zero exit status"))
1794+
end
1795+
1796+
return newtype_ref[]
1797+
end
1798+
17101799
function Type_Contiguous(count::Integer, oldtype)
17111800
newtype_ref = Ref{Cint}()
17121801
flag = Ref{Cint}()

src/win_mpiconstants.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ const MPI_COMM_SELF = Int32(1140850689)
2424
const MPI_COMM_WORLD = Int32(1140850688)
2525
const MPI_COMM_TYPE_SHARED = Int32(1)
2626
const MPI_OP_NULL = Int32(402653184)
27+
const MPI_ORDER_C = Int32(56)
28+
const MPI_ORDER_FORTRAN = Int32(57)
2729
const MPI_BAND = Int32(1476395014)
2830
const MPI_BOR = Int32(1476395016)
2931
const MPI_BXOR = Int32(1476395018)
@@ -122,6 +124,7 @@ const MPI_TESTANY = (:MPI_TESTANY, libmpi)
122124
const MPI_TESTALL = (:MPI_TESTALL, libmpi)
123125
const MPI_TYPE_CONTIGUOUS = (:MPI_TYPE_CONTIGUOUS, libmpi)
124126
const MPI_TYPE_CREATE_STRUCT = (:MPI_TYPE_CREATE_STRUCT, libmpi)
127+
const MPI_TYPE_CREATE_SUBARRAY = (:MPI_TYPE_CREATE_SUBARRAY, libmpi)
125128
const MPI_TYPE_COMMIT = (:MPI_TYPE_COMMIT, libmpi)
126129
const MPI_WAIT = (:MPI_WAIT, libmpi)
127130
const MPI_WAITANY = (:MPI_WAITANY, libmpi)

test/test_subarray.jl

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using Compat
2+
using Test
3+
using MPI
4+
5+
MPI.Init()
6+
7+
comm = MPI.COMM_WORLD
8+
size = MPI.Comm_size(comm)
9+
rank = MPI.Comm_rank(comm)
10+
11+
# assuming there are at least two processes
12+
x = rank == 0 ? collect(reshape(1.0:16.0, 4, 4)) : zeros(4, 4)
13+
14+
subarray = MPI.Type_Create_Subarray(2,
15+
Cint[4, 4],
16+
Cint[2, 2],
17+
Cint[0, 0],
18+
MPI.MPI_ORDER_FORTRAN,
19+
Float64)
20+
MPI.Type_Commit(subarray)
21+
22+
# test blocking send
23+
if rank == 0
24+
MPI.Send(x, 1, subarray, 1, 0, comm)
25+
elseif rank == 1
26+
MPI.Recv!(x, 1, subarray, 0, 0, comm)
27+
@test x == [1 5 0 0;
28+
2 6 0 0;
29+
0 0 0 0;
30+
0 0 0 0]
31+
end
32+
33+
# test non blocking send
34+
if rank == 0
35+
MPI.Isend(x, 1, subarray, 1, 0, comm)
36+
elseif rank == 1
37+
req = MPI.Irecv!(x, 1, subarray, 0, 0, comm)
38+
MPI.Wait!(req)
39+
@test x == [1 5 0 0;
40+
2 6 0 0;
41+
0 0 0 0;
42+
0 0 0 0]
43+
end
44+
45+
MPI.Finalize()

0 commit comments

Comments
 (0)