1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
|
# Assertion modes
# ---------------
MODE_NOCHECK = MPI_MODE_NOCHECK
MODE_NOSTORE = MPI_MODE_NOSTORE
MODE_NOPUT = MPI_MODE_NOPUT
MODE_NOPRECEDE = MPI_MODE_NOPRECEDE
MODE_NOSUCCEED = MPI_MODE_NOSUCCEED
# Lock types
# ----------
LOCK_EXCLUSIVE = MPI_LOCK_EXCLUSIVE
LOCK_SHARED = MPI_LOCK_SHARED
cdef class Win:
"""
Window
"""
def __cinit__(self):
self.ob_mpi = MPI_WIN_NULL
def __dealloc__(self):
if not (self.flags & PyMPI_OWNED): return
CHKERR( _del_Win(&self.ob_mpi) )
def __richcmp__(self, other, int op):
if not isinstance(self, Win): return NotImplemented
if not isinstance(other, Win): return NotImplemented
cdef Win s = self, o = other
if op == 2: return (s.ob_mpi == o.ob_mpi)
elif op == 3: return (s.ob_mpi != o.ob_mpi)
else: raise TypeError(mpistr("only '==' and '!='"))
def __nonzero__(self):
return self.ob_mpi != MPI_WIN_NULL
# [6.2] Initialization
# --------------------
# [6.2.1] Window Creation
# -----------------------
@classmethod
def Create(cls, memory, int disp_unit=1,
Info info=INFO_NULL, Intracomm comm not None=COMM_SELF):
"""
Create an window object for one-sided communication
"""
cdef void* base = MPI_BOTTOM
cdef MPI_Aint size = 0
if memory is not None:
memory = asmemory(memory, &base, &size)
cdef MPI_Info cinfo = _arg_Info(info)
#
cdef Win win = cls()
with nogil: CHKERR( MPI_Win_create(
base, size, disp_unit,
cinfo, comm.ob_mpi, &win.ob_mpi) )
# we are in charge or managing MPI errors
CHKERR( MPI_Win_set_errhandler(win.ob_mpi, MPI_ERRORS_RETURN) )
# hold a reference to the object exposing memory
PyMPI_Win_set_attr_memory(win.ob_mpi, memory)
# return the created window
return win
def Free(self):
"""
Free a window
"""
with nogil: CHKERR( MPI_Win_free(&self.ob_mpi) )
# [6.2.2] Window Attributes
# -------------------------
def Get_group(self):
"""
Return a duplicate of the group of the
communicator used to create the window
"""
cdef Group group = Group()
with nogil: CHKERR( MPI_Win_get_group(self.ob_mpi, &group.ob_mpi) )
return group
property group:
"""window group"""
def __get__(self):
return self.Get_group()
def Get_attr(self, int keyval):
"""
Retrieve attribute value by key
"""
cdef void *attrval = NULL
cdef int flag = 0
CHKERR( MPI_Win_get_attr(self.ob_mpi, keyval, &attrval, &flag) )
if not flag: return None
if not attrval: return 0
# handle predefined keyvals
if (keyval == <int>MPI_WIN_BASE):
return <MPI_Aint>attrval
elif (keyval == <int>MPI_WIN_SIZE):
return (<MPI_Aint*>attrval)[0]
elif (keyval == <int>MPI_WIN_DISP_UNIT):
return (<int*>attrval)[0]
# likely be a user-defined keyval
else:
return PyLong_FromVoidPtr(attrval)
property attrs:
"window attributes"
def __get__(self):
cdef MPI_Win win = self.ob_mpi
cdef void *base = NULL, *pbase = NULL
cdef MPI_Aint size = 0, *psize = NULL
cdef int disp = 0, *pdisp = NULL
cdef int attr = MPI_KEYVAL_INVALID
cdef int flag = 0
#
attr = MPI_WIN_BASE
CHKERR( MPI_Win_get_attr(win, attr, &pbase, &flag) )
if flag and pbase: base = pbase
#
attr = MPI_WIN_SIZE
CHKERR( MPI_Win_get_attr(win, attr, &psize, &flag) )
if flag and psize: size = psize[0]
#
attr = MPI_WIN_DISP_UNIT
CHKERR( MPI_Win_get_attr(win, attr, &pdisp, &flag) )
if flag and pdisp: disp = pdisp[0]
#
return (<MPI_Aint>base, size, disp)
property memory:
"""window memory buffer"""
def __get__(self):
cdef MPI_Win win = self.ob_mpi
cdef void *base = NULL, *pbase = NULL
cdef MPI_Aint size = 0, *psize = NULL
cdef int attr = MPI_KEYVAL_INVALID
cdef int flag = 0
#
attr = MPI_WIN_BASE
CHKERR( MPI_Win_get_attr(win, attr, &pbase, &flag) )
if flag and pbase: base = pbase
#
attr = MPI_WIN_SIZE
CHKERR( MPI_Win_get_attr(win, attr, &psize, &flag) )
if flag and psize: size = psize[0]
#
return tomemory(base, size)
# [6.3] Communication Calls
# -------------------------
# [6.3.1] Put
# -----------
def Put(self, origin, int target_rank, target=None):
"""
Put data into a memory window on a remote process.
"""
cdef _p_msg_rma msg = \
message_rma_put(origin, target_rank, target)
with nogil: CHKERR( MPI_Put(
msg.oaddr, msg.ocount, msg.otype,
target_rank,
msg.tdisp, msg.tcount, msg.ttype,
self.ob_mpi) )
# [6.3.2] Get
# -----------
def Get(self, origin, int target_rank, target=None):
"""
Get data from a memory window on a remote process.
"""
cdef _p_msg_rma msg = \
message_rma_get(origin, target_rank, target)
with nogil: CHKERR( MPI_Get(
msg.oaddr, msg.ocount, msg.otype,
target_rank,
msg.tdisp, msg.tcount, msg.ttype,
self.ob_mpi) )
# [6.3.4] Accumulate Functions
# ----------------------------
def Accumulate(self, origin, int target_rank,
target=None, Op op not None=SUM):
"""
Accumulate data into the target process
using remote memory access.
"""
cdef _p_msg_rma msg = \
message_rma_acc(origin, target_rank, target)
with nogil: CHKERR( MPI_Accumulate(
msg.oaddr, msg.ocount, msg.otype,
target_rank,
msg.tdisp, msg.tcount, msg.ttype,
op.ob_mpi, self.ob_mpi) )
# [6.4] Synchronization Calls
# ---------------------------
# [6.4.1] Fence
# -------------
def Fence(self, int assertion=0):
"""
Perform an MPI fence synchronization on a window
"""
with nogil: CHKERR( MPI_Win_fence(assertion, self.ob_mpi) )
# [6.4.2] General Active Target Synchronization
# ---------------------------------------------
def Start(self, Group group not None, int assertion=0):
"""
Start an RMA access epoch for MPI
"""
with nogil: CHKERR( MPI_Win_start(group.ob_mpi, assertion, self.ob_mpi) )
def Complete(self):
"""
Completes an RMA operations begun after an `Win.Start()`
"""
with nogil: CHKERR( MPI_Win_complete(self.ob_mpi) )
def Post(self, Group group not None, int assertion=0):
"""
Start an RMA exposure epoch
"""
with nogil: CHKERR( MPI_Win_post(group.ob_mpi, assertion, self.ob_mpi) )
def Wait(self):
"""
Complete an RMA exposure epoch begun with `Win.Post()`
"""
with nogil: CHKERR( MPI_Win_wait(self.ob_mpi) )
def Test(self):
"""
Test whether an RMA exposure epoch has completed
"""
cdef bint flag = 0
with nogil: CHKERR( MPI_Win_test(self.ob_mpi, &flag) )
return flag
# [6.4.3] Lock
# ------------
def Lock(self, int lock_type, int rank, int assertion=0):
"""
Begin an RMA access epoch at the target process
"""
with nogil: CHKERR( MPI_Win_lock(lock_type, rank, assertion, self.ob_mpi) )
def Unlock(self, int rank):
"""
Complete an RMA access epoch at the target process
"""
with nogil: CHKERR( MPI_Win_unlock(rank, self.ob_mpi) )
# [6.6] Error Handling
# --------------------
def Get_errhandler(self):
"""
Get the error handler for a window
"""
cdef Errhandler errhandler = Errhandler()
CHKERR( MPI_Win_get_errhandler(self.ob_mpi,
&errhandler.ob_mpi) )
return errhandler
def Set_errhandler(self, Errhandler errhandler not None):
"""
Set the error handler for a window
"""
CHKERR( MPI_Win_set_errhandler(self.ob_mpi, errhandler.ob_mpi) )
def Call_errhandler(self, int errorcode):
"""
Call the error handler installed on a window
"""
CHKERR( MPI_Win_call_errhandler(self.ob_mpi, errorcode) )
# [8.4] Naming Objects
# --------------------
def Get_name(self):
"""
Get the print name associated with the window
"""
cdef char name[MPI_MAX_OBJECT_NAME+1]
cdef int nlen = 0
CHKERR( MPI_Win_get_name(self.ob_mpi, name, &nlen) )
return tompistr(name, nlen)
def Set_name(self, name):
"""
Set the print name associated with the window
"""
cdef char *cname = NULL
name = asmpistr(name, &cname, NULL)
CHKERR( MPI_Win_set_name(self.ob_mpi, cname) )
property name:
"""window name"""
def __get__(self):
return self.Get_name()
def __set__(self, value):
self.Set_name(value)
# Fortran Handle
# --------------
def py2f(self):
"""
"""
return MPI_Win_c2f(self.ob_mpi)
@classmethod
def f2py(cls, arg):
"""
"""
cdef Win win = cls()
win.ob_mpi = MPI_Win_f2c(arg)
return win
cdef Win __WIN_NULL__ = _new_Win(MPI_WIN_NULL)
# Predefined window handles
# -------------------------
WIN_NULL = __WIN_NULL__ #: Null window handle
|