Skip to content

Commit c194631

Browse files
committed
mpi: fix distribution dtype
1 parent c51da27 commit c194631

2 files changed

Lines changed: 24 additions & 17 deletions

File tree

devito/data/distributed/transport.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import numpy as np
1818

1919
from devito.mpi import MPI
20-
from devito.tools import dtype_to_mpidtype
20+
from devito.tools import mpi4py_mapper
2121

2222
__all__ = ['sparse_exchange']
2323

@@ -53,7 +53,15 @@ def sparse_exchange(comm, sendbufs, dtype, tag=0):
5353
"""
5454
rank = comm.Get_rank()
5555
nprocs = comm.Get_size()
56-
mpitype = dtype_to_mpidtype(dtype)
56+
57+
# Some MPI builds lack a native datatype for `dtype` (e.g. `float16`); send
58+
# over a same-size byte-equivalent wire type and view back on receipt, just
59+
# as the halo exchange does via `comm_dtype`. A no-op for mapped-to-self
60+
# types. The MPI datatype is left for mpi4py to infer from each buffer (as
61+
# the halo exchange's `Sendrecv` does): passing an explicit datatype forces
62+
# the `Type_get_extent` count path, which segfaults under some CUDA-aware MPI
63+
# builds, whereas buffer-protocol typing is portable.
64+
wire = np.dtype(mpi4py_mapper.get(np.dtype(dtype).type, dtype))
5765

5866
recvd = {}
5967

@@ -79,19 +87,21 @@ def sparse_exchange(comm, sendbufs, dtype, tag=0):
7987
for peer, buf in sendbufs.items():
8088
if peer == rank or buf.size == 0:
8189
continue
82-
buf = np.ascontiguousarray(buf)
90+
buf = np.ascontiguousarray(buf).view(wire)
8391
live_bufs.append(buf)
84-
sends.append(comm.Isend([buf, mpitype], dest=peer, tag=tag))
92+
sends.append(comm.Isend(buf, dest=peer, tag=tag))
8593

86-
# Receive exactly the expected number of messages, sizing each from its probe
94+
# Receive exactly the expected number of messages, sizing each from its
95+
# probe. The byte count (a probe against `MPI.BYTE`) divides by the wire
96+
# item size to give the element count.
8797
status = MPI.Status()
8898
for _ in range(int(incoming[0])):
8999
comm.Probe(source=MPI.ANY_SOURCE, tag=tag, status=status)
90100
src = status.Get_source()
91-
count = status.Get_count(mpitype)
92-
buf = np.empty(count, dtype=dtype)
93-
comm.Recv([buf, mpitype], source=src, tag=tag)
94-
recvd[src] = buf
101+
count = status.Get_count(MPI.BYTE) // wire.itemsize
102+
buf = np.empty(count, dtype=wire)
103+
comm.Recv(buf, source=src, tag=tag)
104+
recvd[src] = buf.view(dtype)
95105

96106
MPI.Request.Waitall(sends)
97107
return recvd

devito/types/dense.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -695,9 +695,8 @@ def _data_ro_allocated(self):
695695
@cached_property
696696
def local_indices(self):
697697
"""
698-
Per-Dimension slices of the global indices that logically belong to the
699-
calling MPI rank, as a `DimensionTuple` (so it can be indexed positionally
700-
or by Dimension, e.g. `f.local_indices[x]`).
698+
Tuple of slices representing the global indices that logically
699+
belong to the calling MPI rank.
701700
702701
Notes
703702
-----
@@ -707,11 +706,9 @@ def local_indices(self):
707706
decomposition, which is carried by `self.grid`.
708707
"""
709708
if self._distributor is None:
710-
slices = (slice(0, s) for s in self.shape)
711-
else:
712-
slices = (self._distributor.glb_slices.get(d, slice(0, s))
713-
for s, d in zip(self.shape, self.dimensions, strict=True))
714-
return DimensionTuple(*slices, getters=self.dimensions)
709+
return tuple(slice(0, s) for s in self.shape)
710+
return tuple(self._distributor.glb_slices.get(d, slice(0, s))
711+
for s, d in zip(self.shape, self.dimensions, strict=True))
715712

716713
@property
717714
def initializer(self):

0 commit comments

Comments
 (0)