root/ompi/mca/op/example/op_example_module_bxor.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. module_bxor_constructor
  2. module_bxor_destructor
  3. bxor_int
  4. bxor_long
  5. bxor_integer
  6. ompi_op_example_setup_bxor

   1 /*
   2  * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
   3  *                         University Research and Technology
   4  *                         Corporation.  All rights reserved.
   5  * Copyright (c) 2004-2007 The University of Tennessee and The University
   6  *                         of Tennessee Research Foundation.  All rights
   7  *                         reserved.
   8  * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
   9  *                         University of Stuttgart.  All rights reserved.
  10  * Copyright (c) 2004-2005 The Regents of the University of California.
  11  *                         All rights reserved.
  12  * Copyright (c) 2008-2009 Cisco Systems, Inc.  All rights reserved.
  13  * $COPYRIGHT$
  14  *
  15  * Additional copyrights may follow
  16  *
  17  * $HEADER$
  18  */
  19 
  20 /** @file
  21  *
  22  * This is the bxor module source code.  It contains the "setup"
  23  * functions that will create a module for the MPI_BXOR MPI_Op.
  24  */
  25 
  26 #include "ompi_config.h"
  27 
  28 #include "opal/class/opal_object.h"
  29 #include "opal/util/output.h"
  30 
  31 #include "ompi/constants.h"
  32 #include "ompi/op/op.h"
  33 #include "ompi/mca/op/op.h"
  34 #include "ompi/mca/op/base/base.h"
  35 #include "ompi/mca/op/example/op_example.h"
  36 
  37 /**
  38  * Derive a struct from the base op module struct, allowing us to
  39  * cache some module-specific information for BXOR.  Note that
  40  * information that should be shared across all modules should be put
  41  * on the example component.
  42  */
  43 typedef struct {
  44     ompi_op_base_module_1_0_0_t super;
  45 
  46     /* Just like the ompi_op_example_component_t, this struct is meant to
  47        cache information on a per-module basis.  What follows are
  48        examples; replace them with whatever is relevant for your
  49        component/module.  Keep in mind that there will be one distinct
  50        module for each MPI_Op; you may want to have different data
  51        cached on the module, depending on the MPI_Op that it is
  52        supporting.
  53 
  54        In this example, we'll keep the fallback function pointers for
  55        several integer types. */
  56     ompi_op_base_handler_fn_t fallback_int;
  57     ompi_op_base_module_t *fallback_int_module;
  58     ompi_op_base_handler_fn_t fallback_long;
  59     ompi_op_base_module_t *fallback_long_module;
  60     ompi_op_base_handler_fn_t fallback_integer;
  61     ompi_op_base_module_t *fallback_integer_module;
  62 } module_bxor_t;
  63 
  64 /**
  65  * "Constructor" for the bxor module class
  66  */
  67 static void module_bxor_constructor(module_bxor_t *m)
  68 {
  69     /* Use this function to initialize any data in the class that is
  70        specific to this class (i.e. do *not* initialize the parent
  71        data members!). */
  72     m->fallback_int = NULL;
  73     m->fallback_int_module = NULL;
  74     m->fallback_long = NULL;
  75     m->fallback_long_module = NULL;
  76     m->fallback_integer = NULL;
  77     m->fallback_integer_module = NULL;
  78 }
  79 
  80 /**
  81  * "Destructor" for the bxor module class
  82  */
  83 static void module_bxor_destructor(module_bxor_t *m)
  84 {
  85     /* Use this function to clean up any data members that may be
  86        necessary.  This may include freeing resources and/or setting
  87        members to sentinel values to know that the object has been
  88        destructed. */
  89     m->fallback_int = (ompi_op_base_handler_fn_t) 0xdeadbeef;
  90     m->fallback_int_module = (ompi_op_base_module_t*) 0xdeadbeef;
  91     m->fallback_long = (ompi_op_base_handler_fn_t) 0xdeadbeef;
  92     m->fallback_long_module = (ompi_op_base_module_t*) 0xdeadbeef;
  93     m->fallback_integer = (ompi_op_base_handler_fn_t) 0xdeadbeef;
  94     m->fallback_integer_module = (ompi_op_base_module_t*) 0xdeadbeef;
  95 }
  96 
  97 /**
  98  * Setup the class for the bxor module, listing:
  99  * - the name of the class
 100  * - the "parent" of the class
 101  * - function pointer for the constructor (or NULL)
 102  * - function pointer for the destructor (or NULL)
 103  */
 104 static OBJ_CLASS_INSTANCE(module_bxor_t,
 105                           ompi_op_base_module_t,
 106                           module_bxor_constructor,
 107                           module_bxor_destructor);
 108 
 109 /**
 110  * Bxor function for C int
 111  */
 112 static void bxor_int(void *in, void *out, int *count,
 113                     ompi_datatype_t **type, ompi_op_base_module_t *module)
 114 {
 115     module_bxor_t *m = (module_bxor_t*) module;
 116 
 117     /* Be chatty to the output, just so that we can see that this
 118        function was called */
 119     opal_output(0, "In example bxor int function");
 120 
 121     /* This is where you can decide at run-time whether to use the
 122        hardware or the fallback function.  For example, you could have
 123        logic something like this:
 124 
 125        extent = *count * size(int);
 126        if (memory_accessible_on_hw(in, extent) &&
 127            memory_accessible_on_hw(out, extent)) {
 128           ...do the function on hardware...
 129        } else if (extent >= large_enough) {
 130           ...copy host memory -> hardware memory...
 131           ...do the function on hardware...
 132           ...copy hardware memory -> host memory...
 133        } else {
 134           m->fallback_int(in, out, count, type, m->fallback_int_module);
 135        }
 136      */
 137 
 138     /* But for this example, we'll just call the fallback function to
 139        actually do the work */
 140     m->fallback_int(in, out, count, type, m->fallback_int_module);
 141 }
 142 
 143 /**
 144  * Bxor function for C long
 145  */
 146 static void bxor_long(void *in, void *out, int *count,
 147                      ompi_datatype_t **type, ompi_op_base_module_t *module)
 148 {
 149     module_bxor_t *m = (module_bxor_t*) module;
 150     opal_output(0, "In example bxor long function");
 151 
 152     /* Just another example function -- similar to bxor_int() */
 153 
 154     m->fallback_long(in, out, count, type, m->fallback_long_module);
 155 }
 156 
 157 /**
 158  * Bxor function for Fortran INTEGER
 159  */
 160 static void bxor_integer(void *in, void *out, int *count,
 161                         ompi_datatype_t **type, ompi_op_base_module_t *module)
 162 {
 163     module_bxor_t *m = (module_bxor_t*) module;
 164     opal_output(0, "In example bxor integer function");
 165 
 166     /* Just another example function -- similar to bxor_int() */
 167 
 168     m->fallback_integer(in, out, count, type, m->fallback_integer_module);
 169 }
 170 
 171 /**
 172  * Setup function for MPI_BXOR.  If we get here, we can assume that a)
 173  * the hardware is present, b) the MPI thread scenario is what we
 174  * want, and c) the BXOR operation is supported.  So this function's
 175  * job is to create a module and fill in function pointers for the
 176  * functions that this hardware supports.
 177  *
 178  * This function is *not* allowed to changed the op; it can only read
 179  * it to save functions/modules that were already set.  The op base
 180  * will analyze what was returned in the module and re-set values on
 181  * the op if necessary.
 182  */
 183 ompi_op_base_module_t *ompi_op_example_setup_bxor(ompi_op_t *op)
 184 {
 185     module_bxor_t *module = OBJ_NEW(module_bxor_t);
 186 
 187     /* Remember that we created an *example* module (vs. a *base*
 188        module), so we can cache extra information on there that is
 189        specific for the BXOR operation.  Let's cache the original
 190        fallback function pointers, that were passed to us in this call
 191        (i.e., they're already assigned on the op). */
 192 
 193     /* C int */
 194     module->super.opm_fns[OMPI_OP_BASE_TYPE_INT] = bxor_int;
 195     module->fallback_int = op->o_func.intrinsic.fns[OMPI_OP_BASE_TYPE_INT];
 196     module->fallback_int_module =
 197         op->o_func.intrinsic.modules[OMPI_OP_BASE_TYPE_INT];
 198     /* If you cache a fallback function, you *must* RETAIN (i.e.,
 199        increase the refcount) its module so that the module knows that
 200        it is being used and won't be freed/destructed. */
 201     OBJ_RETAIN(module->fallback_int_module);
 202 
 203     /* C long */
 204     module->super.opm_fns[OMPI_OP_BASE_TYPE_LONG] = bxor_long;
 205     module->fallback_long = op->o_func.intrinsic.fns[OMPI_OP_BASE_TYPE_LONG];
 206     module->fallback_long_module =
 207         op->o_func.intrinsic.modules[OMPI_OP_BASE_TYPE_LONG];
 208     OBJ_RETAIN(module->fallback_long_module);
 209 
 210     /* Fortran INTEGER */
 211     module->super.opm_fns[OMPI_OP_BASE_TYPE_INTEGER] = bxor_integer;
 212     module->fallback_integer =
 213         op->o_func.intrinsic.fns[OMPI_OP_BASE_TYPE_INTEGER];
 214     module->fallback_integer_module =
 215         op->o_func.intrinsic.modules[OMPI_OP_BASE_TYPE_INTEGER];
 216     OBJ_RETAIN(module->fallback_integer_module);
 217 
 218     /* ...not listing the rest of the integer-typed functions in this
 219        example... */
 220 
 221     return (ompi_op_base_module_t*) module;
 222 }

/* [<][>][^][v][top][bottom][index][help] */