169. 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, (void *)0) ) { 
       /* 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-3.1 Standard Index
Return to MPI Forum Home Page

(Unofficial) MPI-3.1 of June 4, 2015
HTML Generated on June 4, 2015