Abgeleitete Datentypen . . Kollektive Operationen . . Funktionsübersicht

Hilfesystem für den Message Passing Interface Standard MPI


Beispiel

Verwenden von MPI_Reduce
Beispiel für eine selbstdefinierte globale Operation -
globale Summe mit komplexen Zahlen
#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>

#define  DATA_SIZE 4
#define  TRUE      1

typedef struct {
    int real;
    int imag;
} Complex;

void my_reduce_add(Complex *invec, Complex *inoutvec, int *len, 
                   MPI_Datatype *datatype);
Complex *init_data();

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

    int                 i, choice, stop;
    Complex             *data, *res;
    int                 me, numprocs;
    MPI_Datatype        complext;
    MPI_Op              my_add;
    MPI_User_function   *fmy_reduce_add;

    if (MPI_Init(&argc, &argv)!=MPI_SUCCESS) {
        fprintf( stderr,"MPI_Init failed.\n");
    }
    MPI_Comm_rank(MPI_COMM_WORLD, &me);
    if (me==0)
	fprintf(stderr,"Computing global sum with complex numbers\n");
    MPI_Barrier(MPI_COMM_WORLD);  /* damit die Ausgabe lesbar bleibt */
    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
     MPI_Type_contiguous(2, MPI_INT, &complext);
     MPI_Type_commit(&complext);
    fmy_reduce_add=(MPI_User_function *)&my_reduce_add;
     MPI_Op_create(fmy_reduce_add, TRUE, &my_add);
    data=init_data();
    if (me==0) {
	res=malloc(DATA_SIZE*2*sizeof(int));
    }
    MPI_Barrier(MPI_COMM_WORLD);
    while (!stop) {
        if (me==0) {
	    fprintf(stderr,"1 global sum\n 0 quit\n");
	    fprintf(stderr,"Your choice: ");
	    if (scanf("%d", &choice)!=1) {
	        choice=0;
	    }
        }
         MPI_Bcast(&choice,1,MPI_INT,0,MPI_COMM_WORLD);
        if (choice==1) {
             MPI_Reduce(data, res, DATA_SIZE, complext, my_add,
	                   0, MPI_COMM_WORLD);
        }
        else  stop=1;
        
	if (me==0 && (!stop)) {
	    fprintf(stderr,"Proc %d: Result:\n(", me);
            for (i=0; i<DATA_SIZE; i++) {
	        fprintf(stderr,"%d+%di ", res[i].real, res[i].imag);
            }
	    fprintf(stderr,")\n");
        }
    }
     MPI_Op_free(&my_add);
     MPI_Type_free(&complext);
    MPI_Finalize();
}
    
void my_reduce_add(Complex *invec, Complex *inoutvec, int *len, 
                   MPI_Datatype *datatype) {
    int           i;
    Complex       c;

    for (i=0; i<*len; i++, invec++, inoutvec++) {
	c.real  = invec->real + inoutvec->real;
	c.imag  = invec->imag + inoutvec->imag;
	*inoutvec = c;
    }
}

/* Erzeugt ein paar simple komplexe Zahlen - nur damit was zum Rechnen 
 * da ist ... */

Complex *init_data() {
    Complex   *data;
    int       i, me;
    div_t     x;

    data=malloc(DATA_SIZE*2*sizeof(int));
    MPI_Comm_rank(MPI_COMM_WORLD, &me);
    for (i=0; i<DATA_SIZE; i++) {
	data[i].real=i+1;
	data[i].imag=i+1;
	
    }
    fprintf(stderr,"Proc %d: ", me);
    for (i=0; i<DATA_SIZE; i++) {
	fprintf(stderr,"%d: %d+%di  ", i,data[i].real, data[i].imag);
    }
    fprintf(stderr,"\n");
    return data;
}

Makefile C-Quelltext