OpenMPI  0.1.1
op.h
Go to the documentation of this file.
1 /* -*- Mode: C; c-basic-offset:4 ; -*- */
2 /*
3  * Copyright (c) 2004-2006 The Trustees of Indiana University and Indiana
4  * University Research and Technology
5  * Corporation. All rights reserved.
6  * Copyright (c) 2004-2007 The University of Tennessee and The University
7  * of Tennessee Research Foundation. All rights
8  * reserved.
9  * Copyright (c) 2004-2007 High Performance Computing Center Stuttgart,
10  * University of Stuttgart. All rights reserved.
11  * Copyright (c) 2004-2005 The Regents of the University of California.
12  * All rights reserved.
13  * Copyright (c) 2008 UT-Battelle, LLC
14  * Copyright (c) 2008-2009 Cisco Systems, Inc. All rights reserved.
15  * Copyright (c) 2009 Sun Microsystems, Inc. All rights reserved.
16  * $COPYRIGHT$
17  *
18  * Additional copyrights may follow
19  *
20  * $HEADER$
21  */
22 /**
23  * @file
24  *
25  * Public interface for the MPI_Op handle.
26  */
27 
28 #ifndef OMPI_OP_H
29 #define OMPI_OP_H
30 
31 #include "ompi_config.h"
32 
33 #include <stdio.h>
34 
35 #include "mpi.h"
36 
37 #include "opal/class/opal_object.h"
38 
39 #include "ompi/datatype/ompi_datatype.h"
40 #include "ompi/mpi/f77/fint_2_int.h"
41 #include "ompi/mca/op/op.h"
42 
43 BEGIN_C_DECLS
44 
45 /**
46  * Typedef for C op functions for user-defined MPI_Ops.
47  *
48  * We don't use MPI_User_function because this would create a
49  * confusing dependency loop between this file and mpi.h. So this is
50  * repeated code, but it's better this way (and this typedef will
51  * never change, so there's not much of a maintenance worry).
52  */
53 typedef void (ompi_op_c_handler_fn_t)(void *, void *, int *,
54  struct ompi_datatype_t **);
55 
56 /**
57  * Typedef for fortran user-defined MPI_Ops.
58  */
59 typedef void (ompi_op_fortran_handler_fn_t)(void *, void *,
60  MPI_Fint *, MPI_Fint *);
61 
62 /**
63  * Typedef for C++ op functions intercept (used for user-defined
64  * MPI::Ops).
65  *
66  * See the lengthy explanation for why this is different than the C
67  * intercept in ompi/mpi/cxx/intercepts.cc in the
68  * ompi_mpi_cxx_op_intercept() function.
69  */
70 typedef void (ompi_op_cxx_handler_fn_t)(void *, void *, int *,
71  struct ompi_datatype_t **,
72  MPI_User_function * op);
73 
74 /*
75  * Flags for MPI_Op
76  */
77 /** Set if the MPI_Op is a built-in operation */
78 #define OMPI_OP_FLAGS_INTRINSIC 0x0001
79 /** Set if the callback function is in Fortran */
80 #define OMPI_OP_FLAGS_FORTRAN_FUNC 0x0002
81 /** Set if the callback function is in C++ */
82 #define OMPI_OP_FLAGS_CXX_FUNC 0x0004
83 /** Set if the callback function is associative (MAX and SUM will both
84  have ASSOC set -- in fact, it will only *not* be set if we
85  implement some extensions to MPI, because MPI says that all
86  MPI_Op's should be associative, so this flag is really here for
87  future expansion) */
88 #define OMPI_OP_FLAGS_ASSOC 0x0008
89 /** Set if the callback function is associative for floating point
90  operands (e.g., MPI_SUM will have ASSOC set, but will *not* have
91  FLOAT_ASSOC set) */
92 #define OMPI_OP_FLAGS_FLOAT_ASSOC 0x0010
93 /** Set if the callback function is communative */
94 #define OMPI_OP_FLAGS_COMMUTE 0x0020
95 
96 
97 /**
98  * Back-end type of MPI_Op
99  */
100 struct ompi_op_t {
101  /** Parent class, for reference counting */
103 
104  /** Name, for debugging purposes */
105  char o_name[MPI_MAX_OBJECT_NAME];
106 
107  /** Flags about the op */
108  uint32_t o_flags;
109 
110  /** Index in Fortran <-> C translation array */
112 
113  /** Union holding (2-buffer functions):
114  1. Function pointers for all supported datatypes when this op
115  is intrinsic
116  2. Function pointers for when this op is user-defined (only
117  need one function pointer for this; we call it for *all*
118  datatypes, even intrinsics)
119  */
120  union {
121  /** Function/module pointers for intrinsic ops */
123  /** C handler function pointer */
125  /** Fortran handler function pointer */
127  /** C++ intercept function data -- see lengthy comment in
128  ompi/mpi/cxx/intercepts.cc::ompi_mpi_cxx_op_intercept() for
129  an explanation */
130  struct {
131  /* The user's function (it's the wrong type, but that's ok) */
132  ompi_op_c_handler_fn_t *user_fn;
133  /* The OMPI C++ callback/intercept function */
134  ompi_op_cxx_handler_fn_t *intercept_fn;
135  } cxx_data;
136  } o_func;
137 
138  /** 3-buffer functions, which is only for intrinsic ops. No need
139  for the C/C++/Fortran user-defined functions. */
141 };
142 
143 /**
144  * Convenience typedef
145  */
146 typedef struct ompi_op_t ompi_op_t;
147 OMPI_DECLSPEC OBJ_CLASS_DECLARATION(ompi_op_t);
148 
149 /**
150  * Padded struct to maintain back compatibiltiy.
151  * See ompi/communicator/communicator.h comments with struct ompi_communicator_t
152  * for full explanation why we chose the following padding construct for predefines.
153  */
154 #define PREDEFINED_OP_PAD (sizeof(void*) * 256)
155 
157  struct ompi_op_t op;
158  char padding[PREDEFINED_OP_PAD - sizeof(ompi_op_t)];
159 };
160 
162 
163 /**
164  * Array to map ddt->id values to the corresponding position in the op
165  * function array.
166  *
167  * NOTE: It is possible to have an implementation without this map.
168  * There are basically 3 choices for implementing "how to find the
169  * right position in the op array based on the datatype":
170  *
171  * 1. Use the exact same ordering as ddt->id in the op map. This is
172  * nice in that it's always a direct lookup via one memory
173  * de-reference. But it makes a sparse op array, and it's at least
174  * somewhat wasteful. It also chains the ddt and op implementations
175  * together. If the ddt ever changes its ordering, op is screwed. It
176  * seemed safer from a maintenance point of view not to do it that
177  * way.
178  *
179  * 2. Re-arrange the ddt ID values so that all the reducable types are
180  * at the beginning. This means that we can have a dense array here
181  * in op, but then we have the same problem as number one -- and so
182  * this didn't seem like a good idea from a maintenance point of view.
183  *
184  * 3. Create a mapping between the ddt->id values and the position in
185  * the op array. This allows a nice dense op array, and if we make
186  * the map based on symbolic values, then if ddt ever changes its
187  * ordering, it won't matter to op. This seemed like the safest thing
188  * to do from a maintenance perspective, and since it only costs one
189  * extra lookup, and that lookup is way cheaper than the function call
190  * to invoke the reduction operation, it seemed like the best idea.
191  */
192 OMPI_DECLSPEC extern int ompi_op_ddt_map[OMPI_DATATYPE_MAX_PREDEFINED];
193 
194 /**
195  * Global variable for MPI_OP_NULL
196  */
197 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_null;
198 
199 /**
200  * Global variable for MPI_MAX
201  */
202 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_max;
203 
204 /**
205  * Global variable for MPI_MIN
206  */
207 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_min;
208 
209 /**
210  * Global variable for MPI_SUM
211  */
212 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_sum;
213 
214 /**
215  * Global variable for MPI_PROD
216  */
217 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_prod;
218 
219 /**
220  * Global variable for MPI_LAND
221  */
222 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_land;
223 
224 /**
225  * Global variable for MPI_BAND
226  */
227 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_band;
228 
229 /**
230  * Global variable for MPI_LOR
231  */
232 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_lor;
233 
234 /**
235  * Global variable for MPI_BOR
236  */
237 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_bor;
238 
239 /**
240  * Global variable for MPI_LXOR
241  */
242 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_lxor;
243 
244 /**
245  * Global variable for MPI_BXOR
246  */
247 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_bxor;
248 
249 /**
250  * Global variable for MPI_MAXLOC
251  */
252 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_maxloc;
253 
254 /**
255  * Global variable for MPI_MINLOC
256  */
257 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_minloc;
258 
259 /**
260  * Global variable for MPI_REPLACE
261  */
262 OMPI_DECLSPEC extern ompi_predefined_op_t ompi_mpi_op_replace;
263 
264 
265 /**
266  * Table for Fortran <-> C op handle conversion
267  */
269 
270 /**
271  * Initialize the op interface.
272  *
273  * @returns OMPI_SUCCESS Upon success
274  * @returns OMPI_ERROR Otherwise
275  *
276  * Invoked from ompi_mpi_init(); sets up the op interface, creates
277  * the predefined MPI operations, and creates the corresopnding F2C
278  * translation table.
279  */
280 int ompi_op_init(void);
281 
282 /**
283  * Finalize the op interface.
284  *
285  * @returns OMPI_SUCCESS Always
286  *
287  * Invokes from ompi_mpi_finalize(); tears down the op interface, and
288  * destroys the F2C translation table.
289  */
290 int ompi_op_finalize(void);
291 
292 /**
293  * Create a ompi_op_t with a user-defined callback (vs. creating an
294  * intrinsic ompi_op_t).
295  *
296  * @param commute Boolean indicating whether the operation is
297  * communative or not
298  * @param func Function pointer of the error handler
299  *
300  * @returns op Pointer to the ompi_op_t that will be
301  * created and returned
302  *
303  * This function is called as the back-end of all the MPI_OP_CREATE
304  * function. It creates a new ompi_op_t object, initializes it to the
305  * correct object type, and sets the callback function on it.
306  *
307  * The type of the function pointer is (arbitrarily) the fortran
308  * function handler type. Since this function has to accept 2
309  * different function pointer types (lest we have 2 different
310  * functions to create errhandlers), the fortran one was picked
311  * arbitrarily. Note that (void*) is not sufficient because at
312  * least theoretically, a sizeof(void*) may not necessarily be the
313  * same as sizeof(void(*)).
314  *
315  * NOTE: It *always* sets the "fortran" flag to false. The Fortran
316  * wrapper for MPI_OP_CREATE is expected to reset this flag to true
317  * manually.
318  */
319 ompi_op_t *ompi_op_create_user(bool commute,
321 
322 /**
323  * Mark an MPI_Op as holding a C++ callback function, and cache
324  * that function in the MPI_Op. See a lenghty comment in
325  * ompi/mpi/cxx/op.c::ompi_mpi_cxx_op_intercept() for a full
326  * expalantion.
327  */
328 OMPI_DECLSPEC void ompi_op_set_cxx_callback(ompi_op_t * op,
329  MPI_User_function * fn);
330 
331 /**
332  * Check to see if an op is intrinsic.
333  *
334  * @param op The op to check
335  *
336  * @returns true If the op is intrinsic
337  * @returns false If the op is not intrinsic
338  *
339  * Self-explanitory. This is needed in a few top-level MPI functions;
340  * this function is provided to hide the internal structure field
341  * names.
342  */
343 static inline bool ompi_op_is_intrinsic(ompi_op_t * op)
344 {
345  return (bool) (0 != (op->o_flags & OMPI_OP_FLAGS_INTRINSIC));
346 }
347 
348 
349 /**
350  * Check to see if an op is communative or not
351  *
352  * @param op The op to check
353  *
354  * @returns true If the op is communative
355  * @returns false If the op is not communative
356  *
357  * Self-explanitory. This is needed in a few top-level MPI functions;
358  * this function is provided to hide the internal structure field
359  * names.
360  */
361 static inline bool ompi_op_is_commute(ompi_op_t * op)
362 {
363  return (bool) (0 != (op->o_flags & OMPI_OP_FLAGS_COMMUTE));
364 }
365 
366 /**
367  * Check to see if an op is floating point associative or not
368  *
369  * @param op The op to check
370  *
371  * @returns true If the op is floating point associative
372  * @returns false If the op is not floating point associative
373  *
374  * Self-explanitory. This is needed in a few top-level MPI functions;
375  * this function is provided to hide the internal structure field
376  * names.
377  */
378 static inline bool ompi_op_is_float_assoc(ompi_op_t * op)
379 {
380  return (bool) (0 != (op->o_flags & OMPI_OP_FLAGS_FLOAT_ASSOC));
381 }
382 
383 
384 /**
385  * Check to see if an op is valid on a given datatype
386  *
387  * @param op The op to check
388  * @param ddt The datatype to check
389  *
390  * @returns true If the op is valid on that datatype
391  * @returns false If the op is not valid on that datatype
392  *
393  * Self-explanitory. This is needed in a few top-level MPI functions;
394  * this function is provided to hide the internal structure field
395  * names.
396  */
397 static inline bool ompi_op_is_valid(ompi_op_t * op, ompi_datatype_t * ddt,
398  char **msg, const char *func)
399 {
400  /* Check:
401  - non-intrinsic ddt's cannot be invoked on intrinsic op's
402  - if intrinsic ddt invoked on intrinsic op:
403  - ensure the datatype is defined in the op map
404  - ensure we have a function pointer for that combination
405  */
406 
407  if (ompi_op_is_intrinsic(op)) {
408  if (ompi_datatype_is_predefined(ddt)) {
409  /* Intrinsic ddt on intrinsic op */
410  if (-1 == ompi_op_ddt_map[ddt->id] ||
411  NULL == op->o_func.intrinsic.fns[ompi_op_ddt_map[ddt->id]]) {
412  asprintf(msg,
413  "%s: the reduction operation %s is not defined on the %s datatype",
414  func, op->o_name, ddt->name);
415  return false;
416  }
417  } else {
418  /* Non-intrinsic ddt on intrinsic op */
419  if ('\0' != ddt->name[0]) {
420  asprintf(msg,
421  "%s: the reduction operation %s is not defined for non-intrinsic datatypes (attempted with datatype named \"%s\")",
422  func, op->o_name, ddt->name);
423  } else {
424  asprintf(msg,
425  "%s: the reduction operation %s is not defined for non-intrinsic datatypes",
426  func, op->o_name);
427  }
428  return false;
429  }
430  }
431 
432  /* All other cases ok */
433  return true;
434 }
435 
436 
437 /**
438  * Perform a reduction operation.
439  *
440  * @param op The operation (IN)
441  * @param source Source (input) buffer (IN)
442  * @param target Target (output) buffer (IN/OUT)
443  * @param count Number of elements (IN)
444  * @param dtype MPI datatype (IN)
445  *
446  * @returns void As with MPI user-defined reduction functions, there
447  * is no return code from this function.
448  *
449  * Perform a reduction operation with count elements of type dtype in
450  * the buffers source and target. The target buffer obtains the
451  * result (i.e., the original values in the target buffer are reduced
452  * with the values in the source buffer and the result is stored in
453  * the target buffer).
454  *
455  * This function figures out which reduction operation function to
456  * invoke and whether to invoke it with C- or Fortran-style invocation
457  * methods. If the op is intrinsic and has the operation defined for
458  * dtype, the appropriate back-end function will be invoked.
459  * Otherwise, the op is assumed to be a user op and the first function
460  * pointer in the op array will be used.
461  *
462  * NOTE: This function assumes that a correct combination will be
463  * given to it; it makes no provision for errors (in the name of
464  * optimization). If you give it an intrinsic op with a datatype that
465  * is not defined to have that operation, it is likely to seg fault.
466  */
467 static inline void ompi_op_reduce(ompi_op_t * op, void *source,
468  void *target, int count,
469  ompi_datatype_t * dtype)
470 {
471  MPI_Fint f_dtype, f_count;
472 
473  /*
474  * Call the reduction function. Two dimensions: a) if both the op
475  * and the datatype are intrinsic, we have a series of predefined
476  * functions for each datatype (that are *only* in C -- not
477  * Fortran or C++!), or b) the op is user-defined, and therefore
478  * we have to check whether to invoke the callback with the C,
479  * C++, or Fortran callback signature (see lengthy description of
480  * the C++ callback in ompi/mpi/cxx/intercepts.cc).
481  *
482  * NOTE: We *assume* the following:
483  *
484  * 1. If the op is intrinsic, the op is pre-defined
485  * 2. That we will get a valid result back from the
486  * ompi_op_ddt_map[] (and not -1).
487  *
488  * Failures in these assumptions should have been caught by the
489  * upper layer (i.e., they should never have called this
490  * function). If either of these assumptions are wrong, it's
491  * likely that the MPI API function parameter checking is turned
492  * off, then it's an erroneous program and it's the user's fault.
493  * :-)
494  */
495 
496  /* For intrinsics, we also pass the corresponding op module */
497  if (0 != (op->o_flags & OMPI_OP_FLAGS_INTRINSIC)) {
498  op->o_func.intrinsic.fns[ompi_op_ddt_map[dtype->id]](source, target,
499  &count, &dtype,
500  op->o_func.intrinsic.modules[ompi_op_ddt_map[dtype->id]]);
501  return;
502  }
503 
504  /* User-defined function */
505  if (0 != (op->o_flags & OMPI_OP_FLAGS_FORTRAN_FUNC)) {
506  f_dtype = OMPI_INT_2_FINT(dtype->d_f_to_c_index);
507  f_count = OMPI_INT_2_FINT(count);
508  op->o_func.fort_fn(source, target, &f_count, &f_dtype);
509  return;
510  }
511  if (0 != (op->o_flags & OMPI_OP_FLAGS_CXX_FUNC)) {
512  op->o_func.cxx_data.intercept_fn(source, target, &count, &dtype,
513  op->o_func.cxx_data.user_fn);
514  return;
515  }
516  op->o_func.c_fn(source, target, &count, &dtype);
517  return;
518 }
519 
520 /**
521  * Perform a reduction operation.
522  *
523  * @param op The operation (IN)
524  * @param source Source1 (input) buffer (IN)
525  * @param source Source2 (input) buffer (IN)
526  * @param target Target (output) buffer (IN/OUT)
527  * @param count Number of elements (IN)
528  * @param dtype MPI datatype (IN)
529  *
530  * @returns void As with MPI user-defined reduction functions, there
531  * is no return code from this function.
532  *
533  * Perform a reduction operation with count elements of type dtype in
534  * the buffers source and target. The target buffer obtains the
535  * result (i.e., the original values in the target buffer are reduced
536  * with the values in the source buffer and the result is stored in
537  * the target buffer).
538  *
539  * This function will *only* be invoked on intrinsic MPI_Ops.
540  *
541  * Otherwise, this function is the same as ompi_op_reduce.
542  */
543 static inline void ompi_3buff_op_reduce(ompi_op_t * op, void *source1,
544  void *source2, void *target,
545  int count, ompi_datatype_t * dtype)
546 {
547  void *restrict src1;
548  void *restrict src2;
549  void *restrict tgt;
550  src1 = source1;
551  src2 = source2;
552  tgt = target;
553 
554  op->o_3buff_intrinsic.fns[ompi_op_ddt_map[dtype->id]](src1, src2,
555  tgt, &count,
556  &dtype,
557  op->o_3buff_intrinsic.modules[ompi_op_ddt_map[dtype->id]]);
558 }
559 
560 END_C_DECLS
561 
562 #endif /* OMPI_OP_H */
int o_f_to_c_index
Index in Fortran <-> C translation array.
Definition: op.h:111
Struct that is used in op.h to hold all the function pointers and pointers to the corresopnding modul...
Definition: op.h:400
uint32_t o_flags
Flags about the op.
Definition: op.h:108
struct opal_pointer_array_t * ompi_op_f_to_c_table
Table for Fortran <-> C op handle conversion.
Definition: op.c:34
static bool ompi_op_is_intrinsic(ompi_op_t *op)
Check to see if an op is intrinsic.
Definition: op.h:343
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_null
Global variable for MPI_OP_NULL.
Definition: op.c:61
dynamic pointer array
Definition: opal_pointer_array.h:45
Definition: ompi_datatype.h:68
OMPI_DECLSPEC OBJ_CLASS_DECLARATION(ompi_op_base_module_t)
Declare the module as a class, unversioned.
Struct that is used in op.h to hold all the function pointers and pointers to the corresopnding modul...
Definition: op.h:388
#define OMPI_OP_FLAGS_FORTRAN_FUNC
Set if the callback function is in Fortran.
Definition: op.h:80
opal_object_t super
Parent class, for reference counting.
Definition: op.h:102
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_sum
Global variable for MPI_SUM.
Definition: op.c:64
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_prod
Global variable for MPI_PROD.
Definition: op.c:65
static void ompi_3buff_op_reduce(ompi_op_t *op, void *source1, void *source2, void *target, int count, ompi_datatype_t *dtype)
Perform a reduction operation.
Definition: op.h:543
ompi_op_t * ompi_op_create_user(bool commute, ompi_op_fortran_handler_fn_t func)
Create a ompi_op_t with a user-defined callback (vs.
Definition: op.c:260
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_min
Global variable for MPI_MIN.
Definition: op.c:63
#define OMPI_OP_FLAGS_FLOAT_ASSOC
Set if the callback function is associative for floating point operands (e.g., MPI_SUM will have ASSO...
Definition: op.h:92
char o_name[MPI_MAX_OBJECT_NAME]
Name, for debugging purposes.
Definition: op.h:105
static bool ompi_op_is_commute(ompi_op_t *op)
Check to see if an op is communative or not.
Definition: op.h:361
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_maxloc
Global variable for MPI_MAXLOC.
Definition: op.c:72
ompi_op_base_op_3buff_fns_t o_3buff_intrinsic
3-buffer functions, which is only for intrinsic ops.
Definition: op.h:140
struct ompi_op_t ompi_op_t
Convenience typedef.
Definition: op.h:146
union ompi_op_t::@129 o_func
Union holding (2-buffer functions):
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_lor
Global variable for MPI_LOR.
Definition: op.c:68
static bool ompi_op_is_valid(ompi_op_t *op, ompi_datatype_t *ddt, char **msg, const char *func)
Check to see if an op is valid on a given datatype.
Definition: op.h:397
void( ompi_op_cxx_handler_fn_t)(void *, void *, int *, struct ompi_datatype_t **, MPI_User_function *op)
Typedef for C++ op functions intercept (used for user-defined MPI::Ops).
Definition: op.h:70
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_land
Global variable for MPI_LAND.
Definition: op.c:66
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_minloc
Global variable for MPI_MINLOC.
Definition: op.c:73
#define OMPI_OP_FLAGS_CXX_FUNC
Set if the callback function is in C++.
Definition: op.h:82
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_max
Global variable for MPI_MAX.
Definition: op.c:62
OMPI_DECLSPEC int ompi_op_ddt_map[OMPI_DATATYPE_MAX_PREDEFINED]
Array to map ddt->id values to the corresponding position in the op function array.
Definition: op.c:79
Definition: op.h:156
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_lxor
Global variable for MPI_LXOR.
Definition: op.c:70
char name[MPI_MAX_OBJECT_NAME]
Externally visible name.
Definition: ompi_datatype.h:79
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_replace
Global variable for MPI_REPLACE.
Definition: op.c:74
int ompi_op_init(void)
Initialize the op interface.
Definition: op.c:91
Base object.
Definition: opal_object.h:182
static bool ompi_op_is_float_assoc(ompi_op_t *op)
Check to see if an op is floating point associative or not.
Definition: op.h:378
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_band
Global variable for MPI_BAND.
Definition: op.c:67
#define PREDEFINED_OP_PAD
Padded struct to maintain back compatibiltiy.
Definition: op.h:154
static void ompi_op_reduce(ompi_op_t *op, void *source, void *target, int count, ompi_datatype_t *dtype)
Perform a reduction operation.
Definition: op.h:467
struct ompi_op_t::@129::@130 cxx_data
C++ intercept function data – see lengthy comment in ompi/mpi/cxx/intercepts.cc::ompi_mpi_cxx_op_int...
ompi_op_fortran_handler_fn_t * fort_fn
Fortran handler function pointer.
Definition: op.h:126
#define OMPI_OP_FLAGS_INTRINSIC
Set if the MPI_Op is a built-in operation.
Definition: op.h:78
#define OMPI_OP_FLAGS_COMMUTE
Set if the callback function is communative.
Definition: op.h:94
int32_t d_f_to_c_index
Fortran index for this datatype.
Definition: ompi_datatype.h:73
int32_t id
OMPI-layers unique id of the type.
Definition: ompi_datatype.h:72
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_bor
Global variable for MPI_BOR.
Definition: op.c:69
OMPI_DECLSPEC ompi_predefined_op_t ompi_mpi_op_bxor
Global variable for MPI_BXOR.
Definition: op.c:71
BEGIN_C_DECLS typedef void() ompi_op_c_handler_fn_t(void *, void *, int *, struct ompi_datatype_t **)
Typedef for C op functions for user-defined MPI_Ops.
void( ompi_op_fortran_handler_fn_t)(void *, void *, MPI_Fint *, MPI_Fint *)
Typedef for fortran user-defined MPI_Ops.
Definition: op.h:59
A simple C-language object-oriented system with single inheritance and ownership-based memory managem...
OMPI_DECLSPEC void ompi_op_set_cxx_callback(ompi_op_t *op, MPI_User_function *fn)
Mark an MPI_Op as holding a C++ callback function, and cache that function in the MPI_Op...
Definition: op.c:307
Back-end type of MPI_Op.
Definition: op.h:100
ompi_op_base_op_fns_t intrinsic
Function/module pointers for intrinsic ops.
Definition: op.h:122
MPI_Op back-end operation framework.
int ompi_op_finalize(void)
Finalize the op interface.
Definition: op.c:229
ompi_op_c_handler_fn_t * c_fn
C handler function pointer.
Definition: op.h:124