8.7.6. Attributes Example

PreviousUpNext
Up: Caching Next: Naming Objects Previous: Error Class for Invalid Keyval


Advice to users.

This example shows how to write a collective communication operation that uses caching to be more efficient after the first call. ( 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; 
 
void Efficient_Collective_Op(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_Comm_create_keyval(gop_stuff_copier, 
                             gop_stuff_destructor, 
                             &gop_key, NULL)) { 
    /* get the key while assigning its copy and delete callback 
       behavior. */ 
    } else 
        MPI_Abort(comm, 99); 
  } 
 
  MPI_Comm_get_attr(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_Comm_set_attr(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 */ 
 
int gop_stuff_destructor(MPI_Comm comm, int keyval, void *gop_stuffP,  
                         void *extra) 
{ 
  gop_stuff_type *gop_stuff = (gop_stuff_type *)gop_stuffP; 
  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); 
  } 
  return MPI_SUCCESS; 
} 
 
/* The following routine is called by MPI when a group is copied */ 
int gop_stuff_copier(MPI_Comm comm, int keyval, void *extra,  
               void *gop_stuff_inP, void *gop_stuff_outP, int *flag) 
{ 
  gop_stuff_type *gop_stuff_in = (gop_stuff_type *)gop_stuff_inP; 
  gop_stuff_type **gop_stuff_out = (gop_stuff_type **)gop_stuff_outP; 
  if (keyval != gop_key) { /* abort -- programming error */ } 
 
  /* The new group adds one reference to this gop_stuff */ 
  gop_stuff_in->ref_count += 1; 
  *gop_stuff_out = gop_stuff_in; 
  return MPI_SUCCESS; 
} 


PreviousUpNext
Up: Caching Next: Naming Objects Previous: Error Class for Invalid Keyval


Return to MPI-5.0 Standard Index
Return to MPI Forum Home Page

(Unofficial) MPI-5.0 of June 9, 2025
HTML Generated on March 2, 2025