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 Standard Index
Return to MPI home page