Funktionsübersicht . . Gruppen, Kontexte und Kommunikatoren

Hilfesystem für den Message Passing Interface Standard MPI


Beispiel

für das Zusammenspiel von MPI_Keyval_create, copy_fn, delete_fn und den Funktionen für Attribute. Der vordefinierte Kommunikator MPI_COMM_WORLD wird mit einem Attribut versehen und dann mit MPI_Comm_dup kopiert. Da in delete_fn das flag gesetzt wird, wird das Attribut in den neuen Kommunikator kopiert und dort wieder abgerufen.

#include "mpi.h"
#include <stdio.h>

static int keyval=MPI_KEYVAL_INVALID;

typedef struct {
    int    refcnt;
    char   arch[20];
    int    master;
} attribute_t;

int copy_fn(MPI_Comm *comm, int *keyval, void *extra_state ,
             attribute_t *attribute_val_in, attribute_t **attribute_val_out,
	     int *flag);

int delete_fn(MPI_Comm *comm, int *keyval, attribute_t *attribute_val,
	       void *extra_state );

void glob_sum(MPI_Comm comm, int data, int *sum);
void init_data(int *data);

int main(int argc, char *argv[]) {

    int                   myid, numprocs, i, res, data;
    attribute_t           *attribute_val;
    MPI_Comm              comm, comm2;
    MPI_Copy_function     *copy_ptr;
    MPI_Delete_function   *delete_ptr;

    if (MPI_Init(&argc, &argv)!=MPI_SUCCESS) {
	fprintf( stderr,"MPI_Init failed.\n");
	return -1;
    }

    if (MPI_Keyval_create(
                           (MPI_Copy_function *)& copy_fn, 
                           (MPI_Delete_function *)&delete_fn,
			   &keyval, (void *)0)!=MPI_SUCCESS) {
	fprintf(stderr,"Proc %d: insufficient keys available.\n", myid);
	MPI_Finalize();
	return -2;
    }
    MPI_Comm_rank(MPI_COMM_WORLD, &myid);
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
    attribute_val=(attribute_t *)malloc(sizeof(attribute_t));
    attribute_val->master=numprocs-1;
    attribute_val->refcnt=0;
    if (myid==attribute_val->master) {
#ifdef MPI_LINUX
    sprintf(attribute_val->arch,"LINUX");
#else
    sprintf(attribute_val->arch,"NO_LINUX");
#endif
    }
    MPI_Bcast(&attribute_val->arch, 10, MPI_CHAR,
	      attribute_val->master, MPI_COMM_WORLD);
    
    MPI_Attr_put(MPI_COMM_WORLD, keyval, attribute_val);
    MPI_Comm_dup(MPI_COMM_WORLD, &comm);
    MPI_Comm_rank(comm, &myid);
    init_data(&data);
    MPI_Barrier(comm);
    glob_sum(comm, data, &res);
    /*if (myid==attribute_val->master) {
         fprintf(stderr,"Proc %d: Global sum %d\n", myid, res);
    }*/

    MPI_Comm_free(&comm);

    MPI_Keyval_free(&keyval);
    MPI_Finalize();
}
    
int copy_fn(MPI_Comm *comm, int *keyval, void *extra_state ,
             attribute_t *attribute_val_in, attribute_t **attribute_val_out,
	     int *flag) {

    attribute_val_in->refcnt += 1;
    *flag=1;
    *attribute_val_out=(attribute_t *)malloc(sizeof(attribute_t));
    memcpy(*attribute_val_out, attribute_val_in, sizeof(attribute_t));
    return MPI_SUCCESS;
}
		 	 

int delete_fn(MPI_Comm *comm, int *keyval, attribute_t *attribute_val,
	       void *extra_state) {

    attribute_val->refcnt -= 1;
    free((void *) attribute_val);
    return MPI_SUCCESS;
}

void glob_sum(MPI_Comm comm, int data, int *sum) {

    attribute_t   *attr;
    int           master, flag, myid;

    MPI_Attr_get(comm, keyval, &attr, &flag);
    if (flag) {
	master=attr->master;
	MPI_Comm_rank(comm, &myid);
        fprintf(stderr,"Proc%d: master %d is running on a %s-System (%d)\n",
	        myid, attr->master, attr->arch, attr->refcnt);
    }
    else {
	master=0;
    }
    /* Beispiel für irgendeine Operation, die das Attribut nutzt */
    MPI_Reduce(&data, sum, 1, MPI_INT, MPI_SUM, master, comm);

}

void init_data(int *data) {
/* irgendeine Initialisierung - nur Simulation für Nutzdaten */
    int      me;

    MPI_Comm_rank( MPI_COMM_WORLD, &me);
    *data=me+1;
}

Makefile C-Quelltext