Skip to content

Commit 5f76bce

Browse files
authored
clean up Cartesian topology functions (#536)
Fixes #533.
1 parent 38a1e45 commit 5f76bce

File tree

10 files changed

+84
-95
lines changed

10 files changed

+84
-95
lines changed

docs/src/topology.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
# Topology
22

33
```@docs
4-
MPI.Cart_coords
5-
MPI.Cart_coords!
4+
MPI.Dims_create
65
MPI.Cart_create
76
MPI.Cart_get
7+
MPI.Cart_coords
88
MPI.Cart_rank
99
MPI.Cart_shift
1010
MPI.Cart_sub
1111
MPI.Cartdim_get
12-
MPI.Dims_create!
1312
```

src/deprecated.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,14 @@ import Base: @deprecate
224224
@deprecate(recv(source::Integer, tag::Integer, comm::Comm), recv(comm, MPI.Status; source=source, tag=tag), false)
225225
@deprecate(Sendrecv!(sendbuf, dest::Integer, sendtag::Integer, recvbuf, source::Integer, recvtag::Integer, comm::Comm),
226226
Sendrecv!(sendbuf, recvbuf, comm, MPI.Status; dest=dest, sendtag=sendtag, source=source, recvtag=recvtag)[2], false)
227+
228+
@deprecate(Cart_create(comm_old::Comm, ndims::Integer, dims::MPIBuffertype{Cint}, periods::MPIBuffertype{Cint}, reorder),
229+
Cart_create(comm_old, dims; periodic=periods, reorder=reorder), false)
230+
@deprecate(Cart_create(comm_old::Comm, dims::AbstractArray{T}, periods::Array{T}, reorder) where {T <: Integer},
231+
Cart_create(comm_old, dims; periodic=periods, reorder=reorder), false)
232+
@deprecate(Dims_create!(nnodes::Integer, ndims::Integer, dims::MPIBuffertype{T}) where {T<:Integer},
233+
dims .= Dims_create(nnodes, dims), false)
234+
@deprecate(Dims_create!(nnodes::Integer, dims::AbstractArray{T,N}) where {T<:Integer, N},
235+
dims .= Dims_create(nnodes, dims), false)
236+
@deprecate(Cart_coords!(comm::Comm, rank::Integer, coords::MPIBuffertype{Cint}),
237+
coords .= Cart_coords(comm, rank), false)

src/topology.jl

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,78 @@
11
"""
2-
Dims_create!(nnodes::Integer, [ndims::Integer], dims)
2+
newdims = Dims_create(nnodes::Integer, dims)
33
4-
Create a division of `nnodes` processes in a Cartesian grid.
4+
A convenience function for selecting a balanced Cartesian grid of a total of `nnodes`
5+
nodes, for example to use with [`MPI.Cart_create`](@ref).
6+
7+
`dims` is an array or tuple of integers specifying the number of nodes in each dimension.
8+
The function returns an array `newdims` of the same length, such that if `newdims[i] =
9+
dims[i]` if `dims[i]` is non-zero, and `prod(newdims) == nnodes`, and values `newdims` are
10+
as close to each other as possible.
11+
12+
`nnodes` should be divisible by the product of the non-zero entries of `dims`.
513
614
# External links
715
$(_doc_external("MPI_Dims_create"))
816
"""
9-
function Dims_create!(nnodes::Integer, ndims::Integer, dims::MPIBuffertype{T}) where {T <: Integer}
10-
# int MPI_Dims_create(int nnodes, int ndims, int dims[])
17+
function Dims_create(nnodes::Integer, dims)
18+
dims = Cint[dim for dim in dims]
1119
@mpichk ccall((:MPI_Dims_create, libmpi), Cint,
12-
(Cint, Cint, Ptr{Cint}), nnodes, ndims, dims)
20+
(Cint, Cint, Ptr{Cint}), nnodes, length(dims), dims)
21+
return dims
1322
end
1423

15-
function Dims_create!(nnodes::Integer, dims::AbstractArray{T,N}) where {T<:Integer, N}
16-
cdims = Cint.(dims[:])
17-
ndims = length(cdims)
18-
Dims_create!(nnodes, ndims, cdims)
19-
dims[:] .= cdims
20-
end
2124

2225
"""
23-
comm_cart = Cart_create(comm_old::Comm, [ndims::Integer], dims, periods, reorder)
26+
comm_cart = Cart_create(comm::Comm, dims; periodic=map(_->false, dims), reorder=false)
27+
28+
Create new MPI communicator with Cartesian topology information attached.
2429
25-
Create new MPI communicator with Cartesian structure from an existent communicator.
30+
`dims` is an array or tuple of integers specifying the number of MPI processes in each
31+
coordinate direction, and `periodic` is an array or tuple of `Bool`s indicating the
32+
periodicity of each coordinate. `prod(dims)` must be less than or equal to the size of
33+
`comm`; if it is smaller than some processes are returned a null communicator.
34+
35+
If `reorder == false` then the rank of each process in the new group is identical to its
36+
rank in the old group, otherwise the function may reorder the processes.
37+
38+
See also [`MPI.Dims_create`](@ref).
2639
2740
# External links
2841
$(_doc_external("MPI_Cart_create"))
2942
"""
30-
function Cart_create(comm_old::Comm, ndims::Integer, dims::MPIBuffertype{Cint}, periods::MPIBuffertype{Cint}, reorder)
43+
function Cart_create(comm::Comm, dims; periodic = map(_->false, dims), reorder=false)
44+
if !(dims isa Array{Cint})
45+
dims = Cint[dim for dim in dims]
46+
end
47+
if !(periodic isa Array{Cint})
48+
periodic = Cint[flag for flag in periodic]
49+
end
50+
length(dims) == length(periodic) || error("dims and periodic arguments are not the same length")
3151
comm_cart = Comm()
3252
# int MPI_Cart_create(MPI_Comm comm_old, int ndims, const int dims[],
3353
# const int periods[], int reorder, MPI_Comm *comm_cart)
3454
@mpichk ccall((:MPI_Cart_create, libmpi), Cint,
3555
(MPI_Comm, Cint, Ptr{Cint}, Ptr{Cint}, Cint, Ptr{MPI_Comm}),
36-
comm_old, ndims, dims, periods, reorder, comm_cart)
56+
comm, length(dims), dims, periodic, reorder, comm_cart)
3757
if comm_cart != COMM_NULL
3858
finalizer(free, comm_cart)
3959
end
4060
comm_cart
41-
end
42-
43-
function Cart_create(comm_old::Comm, dims::AbstractArray{T,N}, periods::Array{T,N}, reorder) where T <: Integer where N
44-
cdims = Cint.(dims[:])
45-
cperiods = Cint.(periods[:])
46-
ndims = length(cdims)
47-
Cart_create(comm_old, ndims, cdims, cperiods, reorder)
48-
end
61+
end
4962

5063
"""
5164
rank = Cart_rank(comm::Comm, coords)
5265
53-
Determine process rank in communicator `comm` with Cartesian structure.
54-
The `coords` array specifies the Cartesian coordinates of the process.
66+
Determine process rank in communicator `comm` with Cartesian structure. The `coords`
67+
array specifies the 0-based Cartesian coordinates of the process. This is the inverse of [`MPI.Cart_coords`](@ref)
5568
5669
# External links
5770
$(_doc_external("MPI_Cart_rank"))
5871
"""
59-
function Cart_rank(comm::Comm, coords::MPIBuffertype{Cint})
72+
function Cart_rank(comm::Comm, coords)
73+
if !(coords isa Vector{Cint})
74+
coords = Cint[coord for coord in coords]
75+
end
6076
rank = Ref{Cint}()
6177
# int MPI_Cart_rank(MPI_Comm comm, const int coords[], int *rank)
6278
@mpichk ccall((:MPI_Cart_rank, libmpi), Cint,
@@ -65,10 +81,6 @@ function Cart_rank(comm::Comm, coords::MPIBuffertype{Cint})
6581
Int(rank[])
6682
end
6783

68-
function Cart_rank(comm::Comm, coords::AbstractArray{T}) where {T <: Integer}
69-
ccoords = Cint.(coords[:])
70-
Cart_rank(comm, ccoords)
71-
end
7284

7385
"""
7486
dims, periods, coords = Cart_get(comm::Comm)
@@ -112,34 +124,24 @@ function Cartdim_get(comm::Comm)
112124
end
113125

114126
"""
115-
Cart_coords!(comm::Comm, rank::Integer, coords)
127+
coords = Cart_coords(comm::Comm, rank::Integer=Comm_rank(comm))
116128
117-
Determine coordinates of a given process in Cartesian communicator.
129+
Determine coordinates of a process with rank `rank` in the Cartesian communicator
130+
`comm`. If no `rank` is provided, it returns the coordinates of the current process.
131+
132+
Returns an integer array of the 0-based coordinates. The inverse of [`Cart_rank`](@ref).
118133
119134
# External links
120135
$(_doc_external("MPI_Cart_coords"))
121136
"""
122-
function Cart_coords!(comm::Comm, rank::Integer, coords::MPIBuffertype{Cint})
137+
function Cart_coords(comm::Comm, rank::Integer=Comm_rank(comm))
123138
maxdims = Cartdim_get(comm)
139+
coords = Vector{Cint}(undef, maxdims)
124140
# int MPI_Cart_coords(MPI_Comm comm, int rank, int maxdims, int coords[])
125141
@mpichk ccall((:MPI_Cart_coords, libmpi), Cint,
126142
(MPI_Comm, Cint, Cint, Ptr{Cint}),
127143
comm, rank, maxdims, coords)
128-
end
129-
130-
"""
131-
Cart_coords(comm::Comm)
132-
133-
Determine coordinates of local process in Cartesian communicator.
134-
135-
See also [`Cart_coords!`](@ref).
136-
"""
137-
function Cart_coords(comm::Comm)
138-
maxdims = Cartdim_get(comm)
139-
ccoords = Vector{Cint}(undef, maxdims)
140-
rank = Comm_rank(comm)
141-
Cart_coords!(comm, rank, ccoords)
142-
Int.(ccoords)
144+
return Int.(coords)
143145
end
144146

145147
"""
@@ -174,7 +176,10 @@ be kept in the generated subgrid.
174176
# External links
175177
$(_doc_external("MPI_Cart_sub"))
176178
"""
177-
function Cart_sub(comm::Comm, remain_dims::MPIBuffertype{Cint})
179+
function Cart_sub(comm::Comm, remain_dims)
180+
if !(remain_dims isa Array{Cint})
181+
remain_dims = Cint[dim for dim in remain_dims]
182+
end
178183
comm_sub = Comm()
179184
# int MPI_Cart_sub(MPI_Comm comm, const int remain_dims[], MPI_Comm *comm_new)
180185
@mpichk ccall((:MPI_Cart_sub, libmpi), Cint,
@@ -185,8 +190,3 @@ function Cart_sub(comm::Comm, remain_dims::MPIBuffertype{Cint})
185190
end
186191
comm_sub
187192
end
188-
189-
function Cart_sub(comm::Comm, remain_dims)
190-
cremain_dims = [Cint(dim) for dim in remain_dims]
191-
Cart_sub(comm, cremain_dims)
192-
end

test/test_cart_coords.jl

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ nnodes = MPI.Comm_size(comm)
77
ndims = 3
88
reorder = 1
99
periods = [0,1,0]
10-
dims = [0,0,0]
11-
MPI.Dims_create!(nnodes, dims)
12-
comm_cart = MPI.Cart_create(comm, dims, periods, reorder)
10+
dims = MPI.Dims_create(nnodes, [0,0,0])
11+
comm_cart = MPI.Cart_create(comm, dims; periodic=periods, reorder=reorder)
1312

1413
rank = MPI.Comm_rank(comm)
15-
ccoords = Cint[-1,-1,-1]
16-
MPI.Cart_coords!(comm_cart, rank, ccoords)
14+
ccoords = MPI.Cart_coords(comm_cart, rank)
1715
@test all(ccoords .>= 0)
1816
@test all(ccoords .< dims)
1917

test/test_cart_create.jl

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,14 @@ MPI.Init()
55
comm = MPI.COMM_WORLD
66
nnodes = MPI.Comm_size(comm)
77
ndims = 3
8-
reorder = 1
9-
periods = [0 1 0]
10-
dims = [0 0 0]
11-
MPI.Dims_create!(nnodes, dims)
8+
dims = MPI.Dims_create(nnodes, [0,0,0])
129

1310
@test prod(dims) == nnodes
1411

15-
cperiods = Cint.(periods[:])
16-
cdims = Cint.(dims[:])
17-
comm_cart = MPI.Cart_create(comm, ndims, cdims, cperiods, reorder)
12+
comm_cart = MPI.Cart_create(comm, dims; periodic=[0, 1, 0], reorder=1)
1813
@test MPI.Comm_size(comm_cart) == nnodes
1914

20-
comm_cart2 = MPI.Cart_create(comm, dims, periods, reorder)
15+
comm_cart2 = MPI.Cart_create(comm, dims; periodic=(false, true, false), reorder=true)
2116
@test MPI.Comm_size(comm_cart2) == nnodes
2217

2318
comm_sub1 = MPI.Cart_sub(comm_cart, (false, true, true))

test/test_cart_get.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ periods = Cint[0, 1, 0]
1212
dims = Cint[1, 1, nnodes]
1313

1414
# create
15-
comm_cart = MPI.Cart_create(comm, maxdims, dims, periods, false)
15+
comm_cart = MPI.Cart_create(comm, dims; periodic=periods, reorder=false)
1616

1717
# check number of dimensions
1818
@test MPI.Cartdim_get(comm_cart) == maxdims

test/test_cart_rank.jl

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,15 @@ nnodes = MPI.Comm_size(comm)
77
ndims = 3
88
reorder = 1
99
periods = [0,1,0]
10-
dims = [0,0,0]
11-
MPI.Dims_create!(nnodes, dims)
12-
comm_cart = MPI.Cart_create(comm, dims, periods, reorder)
13-
14-
coords_check = Cint[-1, -1, -1]
10+
dims = MPI.Dims_create(nnodes, [0,0,0])
11+
comm_cart = MPI.Cart_create(comm, dims; periodic=periods, reorder=reorder)
1512

1613
for k = 1:dims[3], j = 1:dims[2], i = 1:dims[1]
1714
cart_coords = [i, j, k] .- 1 # zero-based location
1815
cart_rank = MPI.Cart_rank(comm_cart, cart_coords)
19-
@test cart_rank >= 0
20-
@test cart_rank < nnodes
16+
@test 0 <= cart_rank < nnodes
2117

22-
MPI.Cart_coords!(comm_cart, cart_rank, coords_check)
18+
coords_check = MPI.Cart_coords(comm_cart, cart_rank)
2319
@test all(cart_coords .== coords_check)
2420
end
2521

test/test_cart_shift.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ nnodes = MPI.Comm_size(comm)
77
ndims = 3
88
reorder = 1
99
periods = [0,1,0]
10-
dims = [0,0,0]
11-
MPI.Dims_create!(nnodes, dims)
12-
comm_cart = MPI.Cart_create(comm, dims, periods, reorder)
10+
dims = MPI.Dims_create(nnodes, [0,0,0])
11+
comm_cart = MPI.Cart_create(comm, dims; periodic=periods, reorder=reorder)
1312
coords = MPI.Cart_coords(comm_cart)
1413
disp = 1
1514

test/test_dims_create.jl

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,9 @@ comm = MPI.COMM_WORLD
66
nnodes = MPI.Comm_size(comm)
77
ndims = 3
88

9-
cdims = Cint[0,0,0]
10-
MPI.Dims_create!(nnodes, ndims, cdims)
11-
@test prod(cdims) == nnodes
12-
13-
cdims = Cint[1,0,1]
14-
MPI.Dims_create!(nnodes, ndims, cdims)
15-
@test cdims == Cint[1,nnodes,1]
16-
17-
for dims in ([0,0,0], [0 0 0])
18-
MPI.Dims_create!(nnodes, dims)
19-
@test prod(dims) == nnodes
20-
end
9+
@test prod(MPI.Dims_create(nnodes, (0,0,0))) == nnodes
10+
@test prod(MPI.Dims_create(nnodes, [0,0,0])) == nnodes
11+
@test MPI.Dims_create(nnodes, (1,0,1)) == [1, nnodes, 1]
2112

2213
MPI.Finalize()
2314
@test MPI.Finalized()

test/test_sendrecv.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ comm_size = MPI.Comm_size(comm)
107107
a = Float64[comm_rank, comm_rank, comm_rank]
108108

109109
# construct cartesian communicator with 1D topology
110-
comm_cart = MPI.Cart_create(comm, 1, Cint[comm_size], Cint[1], false)
110+
comm_cart = MPI.Cart_create(comm, (comm_size,); periodic=(true,), reorder=false)
111111

112112
# get source and dest ranks using Cart_shift
113113
src_rank, dest_rank = MPI.Cart_shift(comm_cart, 0, -1)

0 commit comments

Comments
 (0)