## 5.7.2. Attributes Example

Up: Caching Next: Formalizing the Loosely Synchronous Model Previous: Functionality

[] Advice to users.

This example shows how to write a collective communication operation that uses caching to be more efficient after the first call. The coding style assumes that MPI function results return only error statuses. ( End of advice to users.)

    /* key for this module's stuff: */
       static int gop_key = MPI_KEYVAL_INVALID;

    typedef struct
       {
          int ref_count;          /* reference count */
          /* other stuff, whatever else we want */
       } gop_stuff_type;

    Efficient_Collective_Op (comm, ...)
       MPI_Comm comm;
       {
         gop_stuff_type *gop_stuff;
         MPI_Group       group;
         int             foundflag;

    MPI_Comm_group(comm, &group);

    if (gop_key == MPI_KEYVAL_INVALID) /* get a key on first call ever */
         {
           if ( ! MPI_keyval_create( gop_stuff_copier,
                                    gop_stuff_destructor,
                                    &gop_key, (void *)0));
           /* get the key while assigning its copy and delete callback
              behavior. */

    MPI_Abort (comm, 99);
         }

    MPI_Attr_get (comm, gop_key, &gop_stuff, &foundflag);
         if (foundflag)
         { /* This module has executed in this group before.
              We will use the cached information */
         }
         else
         { /* This is a group that we have not yet cached anything in.
              We will now do so.
           */

    /* First, allocate storage for the stuff we want,
              and initialize the reference count */

    gop_stuff = (gop_stuff_type *) malloc (sizeof(gop_stuff_type));
           if (gop_stuff == NULL) { /* abort on out-of-memory error */ }

    gop_stuff -> ref_count = 1;

    /* Second, fill in *gop_stuff with whatever we want.
              This part isn't shown here */

    /* Third, store gop_stuff as the attribute value */
           MPI_Attr_put ( comm, gop_key, gop_stuff);
         }
         /* Then, in any case, use contents of *gop_stuff
            to do the global op ... */
       }

    /* The following routine is called by MPI when a group is freed */

    gop_stuff_destructor (comm, keyval, gop_stuff, extra)
       MPI_Comm comm;
       int keyval;
       gop_stuff_type *gop_stuff;
       void *extra;
       {
         if (keyval != gop_key) { /* abort -- programming error */ }

    /* The group's being freed removes one reference to gop_stuff */
         gop_stuff -> ref_count -= 1;

    /* If no references remain, then free the storage */
         if (gop_stuff -> ref_count == 0) {
           free((void *)gop_stuff);
         }
       }

    /* The following routine is called by MPI when a group is copied */
       gop_stuff_copier (comm, keyval, extra, gop_stuff_in, gop_stuff_out, flag)
       MPI_Comm comm;
       int keyval;
       gop_stuff_type *gop_stuff_in, *gop_stuff_out;
       void *extra;
       {
         if (keyval != gop_key) { /* abort -- programming error */ }

    /* The new group adds one reference to this gop_stuff */
         gop_stuff -> ref_count += 1;
         gop_stuff_out = gop_stuff_in;
       }

Up: Caching Next: Formalizing the Loosely Synchronous Model Previous: Functionality

Return to MPI 1.1 Standard Index
Return to MPI-2 Standard Index
Return to MPI Forum Home Page

MPI-1.1 of June 12, 1995
HTML Generated on August 6, 1997