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

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

DEFINITIONS

This source file includes following definitions.
  1. module_max_constructor
  2. module_max_destructor
  3. max_float
  4. max_double
  5. max_real
  6. max_double_precision
  7. ompi_op_example_setup_max

   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 max module source code.  It contains the "setup"
  23  * functions that will create a module for the MPI_MAX 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 MAX.  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_float;
  57     ompi_op_base_module_t *fallback_float_module;
  58     ompi_op_base_handler_fn_t fallback_real;
  59     ompi_op_base_module_t *fallback_real_module;
  60 
  61     ompi_op_base_handler_fn_t fallback_double;
  62     ompi_op_base_module_t *fallback_double_module;
  63     ompi_op_base_handler_fn_t fallback_double_precision;
  64     ompi_op_base_module_t *fallback_double_precision_module;
  65 } module_max_t;
  66 
  67 /**
  68  * "Constructor" for the max module class
  69  */
  70 static void module_max_constructor(module_max_t *m)
  71 {
  72     /* Use this function to initialize any data in the class that is
  73        specific to this class (i.e. do *not* initialize the parent
  74        data members!). */
  75     m->fallback_float = NULL;
  76     m->fallback_float_module = NULL;
  77     m->fallback_real = NULL;
  78     m->fallback_real_module = NULL;
  79 
  80     m->fallback_double = NULL;
  81     m->fallback_double_module = NULL;
  82     m->fallback_double_precision = NULL;
  83     m->fallback_double_precision_module = NULL;
  84 }
  85 
  86 /**
  87  * "Destructor" for the max module class
  88  */
  89 static void module_max_destructor(module_max_t *m)
  90 {
  91     /* Use this function to clean up any data members that may be
  92        necessary.  This may include freeing resources and/or setting
  93        members to sentinel values to know that the object has been
  94        destructed. */
  95     m->fallback_float = (ompi_op_base_handler_fn_t) 0xdeadbeef;
  96     m->fallback_float_module = (ompi_op_base_module_t*) 0xdeadbeef;
  97     m->fallback_real = (ompi_op_base_handler_fn_t) 0xdeadbeef;
  98     m->fallback_real_module = (ompi_op_base_module_t*) 0xdeadbeef;
  99 
 100     m->fallback_double = (ompi_op_base_handler_fn_t) 0xdeadbeef;
 101     m->fallback_double_module = (ompi_op_base_module_t*) 0xdeadbeef;
 102     m->fallback_double_precision = (ompi_op_base_handler_fn_t) 0xdeadbeef;
 103     m->fallback_double_precision_module = (ompi_op_base_module_t*) 0xdeadbeef;
 104 }
 105 
 106 /**
 107  * Setup the class for the max module, listing:
 108  * - the name of the class
 109  * - the "parent" of the class
 110  * - function pointer for the constructor (or NULL)
 111  * - function pointer for the destructor (or NULL)
 112  */
 113 static OBJ_CLASS_INSTANCE(module_max_t,
 114                           ompi_op_base_module_t,
 115                           module_max_constructor,
 116                           module_max_destructor);
 117 
 118 /**
 119  * Max function for C float
 120  */
 121 static void max_float(void *in, void *out, int *count,
 122                       ompi_datatype_t **type, ompi_op_base_module_t *module)
 123 {
 124     module_max_t *m = (module_max_t*) module;
 125 
 126     /* Be chatty to the output, just so that we can see that this
 127        function was called */
 128     opal_output(0, "In example max float function");
 129 
 130     /* This is where you can decide at run-time whether to use the
 131        hardware or the fallback function.  For example, you could have
 132        logic something like this:
 133 
 134        extent = *count * size(int);
 135        if (memory_accessible_on_hw(in, extent) &&
 136            memory_accessible_on_hw(out, extent)) {
 137           ...do the function on hardware...
 138        } else if (extent >= large_enough) {
 139           ...copy host memory -> hardware memory...
 140           ...do the function on hardware...
 141           ...copy hardware memory -> host memory...
 142        } else {
 143           m->fallback_float(in, out, count, type, m->fallback_int_module);
 144        }
 145      */
 146 
 147     /* But for this example, we'll just call the fallback function to
 148        actually do the work */
 149     m->fallback_float(in, out, count, type, m->fallback_float_module);
 150 }
 151 
 152 /**
 153  * Max function for C double
 154  */
 155 static void max_double(void *in, void *out, int *count,
 156                        ompi_datatype_t **type, ompi_op_base_module_t *module)
 157 {
 158     module_max_t *m = (module_max_t*) module;
 159     opal_output(0, "In example max double function");
 160 
 161     /* Just another example function -- similar to max_int() */
 162 
 163     m->fallback_double(in, out, count, type, m->fallback_double_module);
 164 }
 165 
 166 /**
 167  * Max function for Fortran REAL
 168  */
 169 static void max_real(void *in, void *out, int *count,
 170                      ompi_datatype_t **type, ompi_op_base_module_t *module)
 171 {
 172     module_max_t *m = (module_max_t*) module;
 173     opal_output(0, "In example max real function");
 174 
 175     /* Just another example function -- similar to max_int() */
 176 
 177     m->fallback_real(in, out, count, type, m->fallback_real_module);
 178 }
 179 
 180 /**
 181  * Max function for Fortran DOUBLE PRECISION
 182  */
 183 static void max_double_precision(void *in, void *out, int *count,
 184                                  ompi_datatype_t **type,
 185                                  ompi_op_base_module_t *module)
 186 {
 187     module_max_t *m = (module_max_t*) module;
 188     opal_output(0, "In example max double precision function");
 189 
 190     /* Just another example function -- similar to max_int() */
 191 
 192     m->fallback_double_precision(in, out, count, type,
 193                                  m->fallback_double_precision_module);
 194 }
 195 
 196 /**
 197  * Setup function for MPI_MAX.  If we get here, we can assume that a)
 198  * the hardware is present, b) the MPI thread scenario is what we
 199  * want, and c) the MAX operation is supported.  So this function's
 200  * job is to create a module and fill in function pointers for the
 201  * functions that this hardware supports.
 202  */
 203 ompi_op_base_module_t *ompi_op_example_setup_max(ompi_op_t *op)
 204 {
 205     module_max_t *module = OBJ_NEW(module_max_t);
 206 
 207     /* We defintely support the single precision floating point types */
 208 
 209     /* Remember that we created an *example* module (vs. a *base*
 210        module), so we can cache extra information on there that is
 211        specific for the MAX operation.  Let's cache the original
 212        fallback function pointers, that were passed to us in this call
 213        (i.e., they're already assigned on the op). */
 214 
 215     /* C float */
 216     module->super.opm_fns[OMPI_OP_BASE_TYPE_FLOAT] = max_float;
 217     module->fallback_float = op->o_func.intrinsic.fns[OMPI_OP_BASE_TYPE_FLOAT];
 218     module->fallback_float_module =
 219         op->o_func.intrinsic.modules[OMPI_OP_BASE_TYPE_FLOAT];
 220     /* If you cache a fallback function, you *must* RETAIN (i.e.,
 221        increase the refcount) its module so that the module knows that
 222        it is being used and won't be freed/destructed. */
 223     OBJ_RETAIN(module->fallback_float_module);
 224 
 225     /* Fortran REAL */
 226     module->super.opm_fns[OMPI_OP_BASE_TYPE_REAL] = max_real;
 227     module->fallback_real =
 228         op->o_func.intrinsic.fns[OMPI_OP_BASE_TYPE_REAL];
 229     module->fallback_real_module =
 230         op->o_func.intrinsic.modules[OMPI_OP_BASE_TYPE_REAL];
 231     OBJ_RETAIN(module->fallback_real_module);
 232 
 233     /* Does our hardware support double precision? */
 234 
 235     if (mca_op_example_component.double_supported) {
 236         /* C double */
 237         module->super.opm_fns[OMPI_OP_BASE_TYPE_DOUBLE] = max_double;
 238         module->fallback_double =
 239             op->o_func.intrinsic.fns[OMPI_OP_BASE_TYPE_DOUBLE];
 240         module->fallback_double_module =
 241             op->o_func.intrinsic.modules[OMPI_OP_BASE_TYPE_DOUBLE];
 242         OBJ_RETAIN(module->fallback_double_module);
 243 
 244         /* Fortran DOUBLE PRECISION */
 245         module->super.opm_fns[OMPI_OP_BASE_TYPE_DOUBLE_PRECISION] =
 246             max_double_precision;
 247         module->fallback_double_precision =
 248             op->o_func.intrinsic.fns[OMPI_OP_BASE_TYPE_DOUBLE_PRECISION];
 249         module->fallback_double_precision_module =
 250             op->o_func.intrinsic.modules[OMPI_OP_BASE_TYPE_DOUBLE_PRECISION];
 251         OBJ_RETAIN(module->fallback_double_precision_module);
 252     }
 253 
 254     /* ...not listing the rest of the floating point-typed functions
 255        in this example... */
 256 
 257     return (ompi_op_base_module_t*) module;
 258 }

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