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

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

DEFINITIONS

This source file includes following definitions.
  1. example_component_open
  2. example_component_close
  3. example_component_register
  4. example_component_init_query
  5. example_component_op_query

   1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
   2 /*
   3  * Copyright (c) 2004-2007 The Trustees of Indiana University and Indiana
   4  *                         University Research and Technology
   5  *                         Corporation.  All rights reserved.
   6  * Copyright (c) 2004-2011 The University of Tennessee and The University
   7  *                         of Tennessee Research Foundation.  All rights
   8  *                         reserved.
   9  * Copyright (c) 2004-2005 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-2009 Cisco Systems, Inc.  All rights reserved.
  14  * Copyright (c) 2015      Los Alamos National Security, LLC. All rights
  15  *                         reserved.
  16  * Copyright (c) 2018      Amazon.com, Inc. or its affiliates.  All Rights reserved.
  17  * $COPYRIGHT$
  18  *
  19  * Additional copyrights may follow
  20  *
  21  * $HEADER$
  22  */
  23 
  24 /** @file
  25  *
  26  * This is the "example" component source code.  It contains the
  27  * well-known struct that OMPI will dlsym() (or equivalent) for to
  28  * find how to access the rest of the component and any modules that
  29  * are created.
  30  */
  31 
  32 #include "ompi_config.h"
  33 
  34 #include "opal/util/printf.h"
  35 
  36 #include "ompi/constants.h"
  37 #include "ompi/op/op.h"
  38 #include "ompi/mca/op/op.h"
  39 #include "ompi/mca/op/base/base.h"
  40 #include "ompi/mca/op/example/op_example.h"
  41 
  42 static int example_component_open(void);
  43 static int example_component_close(void);
  44 static int example_component_init_query(bool enable_progress_threads,
  45                                      bool enable_mpi_thread_multiple);
  46 static struct ompi_op_base_module_1_0_0_t *
  47     example_component_op_query(struct ompi_op_t *op, int *priority);
  48 static int example_component_register(void);
  49 
  50 ompi_op_example_component_t mca_op_example_component = {
  51     /* First, the mca_base_component_t struct containing meta
  52        information about the component itself */
  53     {
  54         .opc_version = {
  55             OMPI_OP_BASE_VERSION_1_0_0,
  56 
  57             .mca_component_name = "example",
  58             MCA_BASE_MAKE_VERSION(component, OMPI_MAJOR_VERSION, OMPI_MINOR_VERSION,
  59                                   OMPI_RELEASE_VERSION),
  60             .mca_open_component = example_component_open,
  61             .mca_close_component = example_component_close,
  62             .mca_register_component_params = example_component_register,
  63         },
  64         .opc_data = {
  65             /* The component is checkpoint ready */
  66             MCA_BASE_METADATA_PARAM_CHECKPOINT
  67         },
  68 
  69         .opc_init_query = example_component_init_query,
  70         .opc_op_query = example_component_op_query,
  71     },
  72 
  73     /* Now comes the example-component-specific data.  In this case,
  74        we'll just leave it blank, defaulting all the values to
  75        0/false/whatever.  We'll fill them in with meaningful values
  76        during _component_init_query(). */
  77 };
  78 
  79 /*
  80  * Component open
  81  */
  82 static int example_component_open(void)
  83 {
  84     opal_output(ompi_op_base_framework.framework_output, "example component open");
  85 
  86     /* A first level check to see if example is even available in this
  87        process.  E.g., you may want to do a first-order check to see
  88        if hardware is available.  If so, return OMPI_SUCCESS.  If not,
  89        return anything other than OMPI_SUCCESS and the component will
  90        silently be ignored.
  91 
  92        Note that if this function returns non-OMPI_SUCCESS, then this
  93        component won't even be shown in ompi_info output (which is
  94        probably not what you want).
  95     */
  96 
  97     return OMPI_SUCCESS;
  98 }
  99 
 100 
 101 /*
 102  * Component close
 103  */
 104 static int example_component_close(void)
 105 {
 106     opal_output(ompi_op_base_framework.framework_output, "example component close");
 107 
 108     /* If example was opened successfully, close it (i.e., release any
 109        resources that may have been allocated on this component).
 110        Note that _component_close() will always be called at the end
 111        of the process, so it may have been after any/all of the other
 112        component functions have been invoked (and possibly even after
 113        modules have been created and/or destroyed). */
 114 
 115     return OMPI_SUCCESS;
 116 }
 117 
 118 static char *example_component_version;
 119 
 120 /*
 121  * Register MCA params.
 122  */
 123 static int example_component_register(void)
 124 {
 125     int val;
 126     char *str;
 127 
 128     opal_output(ompi_op_base_framework.framework_output, "example component register");
 129 
 130     /* Register any relevant MCA params.  At a minimum, perhaps some
 131        information MCA params that return version and capability
 132        information.  */
 133 
 134     /* For example, let's make a string MCA information parameter
 135        containing the major.minor.release version number from the
 136        libfoo support library (see configure.m4 for how we got these C
 137        macros). */
 138     opal_asprintf(&str, "%s.%s.%s",
 139              OP_EXAMPLE_LIBFOO_VERSION_MAJOR,
 140              OP_EXAMPLE_LIBFOO_VERSION_MINOR,
 141              OP_EXAMPLE_LIBFOO_VERSION_RELEASE);
 142     example_component_version = str;
 143     (void) mca_base_component_var_register(&mca_op_example_component.super.opc_version,
 144                                            "libfoo_version",
 145                                            "Version of the libfoo support library that this component was built against.",
 146                                            MCA_BASE_VAR_TYPE_STRING, NULL, 0,
 147                                            MCA_BASE_VAR_FLAG_DEFAULT_ONLY,
 148                                            OPAL_INFO_LVL_9,
 149                                            MCA_BASE_VAR_SCOPE_CONSTANT,
 150                                            &example_component_version);
 151     /* The variable system duplicated the string. */
 152     free(str);
 153 
 154     /* Additionally, since this component is simulating hardware,
 155        let's make MCA params that determine whethere a) the hardware
 156        is available, and b) whether double precision floating point
 157        types are supported.  This allows you to change the behavior of
 158        this component at run-time (by setting these MCA params at
 159        run-time), simulating different kinds of hardware. */
 160     mca_op_example_component.hardware_available = false;
 161     (void) mca_base_component_var_register(&mca_op_example_component.super.opc_version,
 162                                            "hardware_available",
 163                                            "Whether the hardware is available or not",
 164                                            MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
 165                                            OPAL_INFO_LVL_9,
 166                                            MCA_BASE_VAR_SCOPE_READONLY,
 167                                            &mca_op_example_component.hardware_available);
 168 
 169     mca_op_example_component.double_supported = true;
 170     (void) mca_base_component_var_register(&mca_op_example_component.super.opc_version,
 171                                            "double_supported",
 172                                            "Whether the double precision data types are supported or not",
 173                                            MCA_BASE_VAR_TYPE_BOOL, NULL, 0, 0,
 174                                            OPAL_INFO_LVL_9,
 175                                            MCA_BASE_VAR_SCOPE_READONLY,
 176                                            &mca_op_example_component.double_supported);
 177 
 178     return OMPI_SUCCESS;
 179 }
 180 
 181 
 182 /*
 183  * Query whether this component wants to be used in this process.
 184  */
 185 static int example_component_init_query(bool enable_progress_threads,
 186                                         bool enable_mpi_thread_multiple)
 187 {
 188     opal_output(ompi_op_base_framework.framework_output, "example component init query");
 189 
 190     /* Query to see if we have the desired hardware / resources to be
 191        able to perform reduction operations.  This is a much more
 192        comprehensive check than _component_open().
 193 
 194        If this component can be used in this process, return
 195        OMPI_SUCCESS, meaning that we'll be queried later via during
 196        the MPI_Op component selection process via
 197        _component_op_query().  Otherwise, return anything other than
 198        OMPI_SUCCESS and this component will be silently ignored for
 199        the MPI_Op component selection process.
 200 
 201        The input parameters enable_progress_threads and
 202        enable_mpi_thread_multiple also tell the component the following:
 203 
 204        - If enable_progress_threads==true, then the component is
 205          allowed to have a progress thread in the background that is
 206          supported by the OMPI infrastructure (i.e., all of OMPI's
 207          locks and whatnot are active in this build).  Note that the
 208          component can *always* have a progress thread in the
 209          background regardless of the value of this parameter as lone
 210          as the HAVE_THREADS macro is true and the component uses its
 211          own locking schemes (i.e., does not rely on external
 212          OPAL/OMPI data structures to be thread safe).  This flag
 213          simply indicates whether OPAL/OMPI data structures are
 214          multi-threaded safe and whether multi-threading sync/IPC
 215          mechanisms in the OMPI code base are active.
 216 
 217        - If enable_mpi_thread_multiple==true, then MPI_THREAD_MULTIPLE is
 218          active.
 219 
 220        Note that a component can uses these values to deactivate
 221        themselves if multi-threading is not supported (keep in mind
 222        that in MPI_THREAD_MULTIPLE scenarios, the same MPI_Op can be
 223        used in multiple, concurrent operations in different threads).
 224        Let's assume that this component does not support
 225        MPI_THREAD_MULTIPLE, and will therefore deactivate itself if
 226        MPI_THREAD_MULTIPLE is used.
 227     */
 228 
 229     /* Note that we used MCA parameters to fill in the
 230        _component.hardware_available and _component.double_supported
 231        values.  Typically, you'd probe the hardware here and fill in
 232        those values instead of using MCA parameters (the MCA params
 233        are only used in this example to allow simulating different
 234        types of hardware). */
 235 
 236     /* If we have the hardware and are not using MPI_THREAD_MULITPLE,
 237        return OMPI_SUCCESS (indicating that _component_op_query() will
 238        be called in the future for each intrinsic MPI_Op).  Otherwise,
 239        return OMPI_ERR_NOT_SUPPORTED (indicating that this component
 240        will be closed and discarded). */
 241     if (mca_op_example_component.hardware_available && !enable_mpi_thread_multiple) {
 242         return OMPI_SUCCESS;
 243     }
 244     return OMPI_ERR_NOT_SUPPORTED;
 245 }
 246 
 247 
 248 /*
 249  * Query whether this component can be used for a specific op
 250  */
 251 static struct ompi_op_base_module_1_0_0_t *
 252     example_component_op_query(struct ompi_op_t *op, int *priority)
 253 {
 254     ompi_op_base_module_t *module = NULL;
 255 
 256     opal_output(ompi_op_base_framework.framework_output, "example component op query");
 257 
 258     /* Sanity check -- although the framework should never invoke the
 259        _component_op_query() on non-intrinsic MPI_Op's, we'll put a
 260        check here just to be sure. */
 261     if (0 == (OMPI_OP_FLAGS_INTRINSIC & op->o_flags)) {
 262         opal_output(0, "example component op query: not an intrinsic MPI_Op -- skipping");
 263         return NULL;
 264     }
 265 
 266     /* What follows is an example of how to determine whether your
 267        component supports the queried MPI_Op.  You can do this lots of
 268        different ways; this is but one example. */
 269 
 270     /* Note that we *do* have the hardware; _component_init_query()
 271        would not have returned OMPI_SUCCESS if we didn't have the
 272        hardware (and therefore this function would never have been
 273        called).  So we don't need to check for the hardware again.
 274        Instead, we need to do finer-grained checks (e.g., do we
 275        support this op, and if so, what datatypes are supported?).
 276 
 277        So check to see whether this MPI_Op operation is supported on
 278        the hardware that this component supports (which may involve
 279        querying the hardware to see what it is capable of).
 280 
 281        You can see what operation is being requested by checking the
 282        "op->o_f_to_c_index" value against the OMPI_OP_BASE_FORTRAN_*
 283        enums.  See ompi/mca/op/op.h for a full list of the
 284        OMPI_OP_BASE_FORTRAN_* enums.
 285 
 286        In this example component, we support MAX and BXOR. */
 287     switch (op->o_f_to_c_index) {
 288     case OMPI_OP_BASE_FORTRAN_MAX:
 289         /* Corresponds to MPI_MAX */
 290         module = ompi_op_example_setup_max(op);
 291         break;
 292 
 293     case OMPI_OP_BASE_FORTRAN_BXOR:
 294         /* Corresponds to MPI_BXOR */
 295         module = ompi_op_example_setup_bxor(op);
 296         break;
 297     }
 298 
 299     /* If we got a module from above, we'll return it.  Otherwise,
 300        we'll return NULL, indicating that this component does not want
 301        to be considered for selection for this MPI_Op.  Note that the
 302        "setup" functions each returned a *example* component pointer
 303        (vs. a *base* component pointer -- where an *example* component
 304        is a base component plus some other module-specific cached
 305        information), so we have to cast it to the right pointer type
 306        before returning. */
 307     if (NULL != module) {
 308         *priority = 50;
 309     }
 310     return (ompi_op_base_module_1_0_0_t *) module;
 311 }

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