include MPI header file variable declarations initialize the MPI environment ...do computation and MPI communication calls... close MPI communications
MPI_ und haben int als Rückgabewert (sollte MPI_SUCCESS sein)MPI_CHAR, MPI_SHORT, MPI_INT, MPI_LONG, MPI_UNSIGNED_CHAR, MPI_UNSIGNED_SHORT, MPI_UNSIGNED, MPI_UNSIGNED_LONG, MPI_FLOAT, MPI_DOUBLE, MPI_LONG_DOUBLE, MPI_BYTE, MPI_PACKEDMPI_COMM, MPI_STATUS, MPI_DATATYPEint err; err = MPI_Init(&argc, &argv);
MPI_COMM_WORLD), ihren Rang in einem Communicator erhalten sie mit int MPI_Comm_rank(MPI_Comm comm, int *rank);
int MPI_Comm_size(MPI_Comm comm, int *size);
err = MPI_Finalize();
#include <stdio.h>
#include <mpi.h>
void main (int argc, char *argv[])
{
int myrank, size;
MPI_Init(&argc, &argv); // Initialize MPI
MPI_Comm_rank(MPI_COMM_WORLD, &myrank); // Get my rank
MPI_Comm_size(MPI_COMM_WORLD, &size); // Get the total number of processors
printf("Processor %d of %d: Hello World!\n", myrank, size);
MPI_Finalize(); // Terminate MPI
}
int MPI_Send(void *buf, int count, MPI_Datatype dtype, int dest, int tag, MPI_Comm comm);
int MPI_Recv(void *buf, int count, MPI_Datatype dtype, int source, int tag, MPI_Comm comm, MPI_Status *status);
source, tag und communicator müssen den Werten aus MPI_Send entsprechen (Wildcards sind erlaubt für source und tag)buffer und status sind Output-Parameter, der Rest InputMPI_ANY_SOURCE und MPI_ANY_TAG sind die Wildcardsstatus.MPI_SOURCE und status.MPI_TAG können die konkreten Werte ermittelt werdencount ist lediglich das Maximum der möglichen Werte): int MPI_Get_count(MPI_Status *status, MPI_Datatype dtype, int *count);
MPI_SEND zurückkehrt heißt das nicht, dass die Nachricht angekommen ist, sondern nur, dass sie MPI übergeben wurdeint MPI_Isend(void *buf, int count, MPI_Datatype dtype, int dest, int tag, MPI_Comm comm, MPI_Request *request);
int MPI_Irecv(void *buf, int count, MPI_Datatype dtype, int source, int tag, MPI_Comm comm, MPI_Request *request);
int MPI_Wait( MPI_Request *request, MPI_Status *status );
int MPI_Test( MPI_Request *request, int *flag, MPI_Status *status );
MPI_IRECV(...,request)
...
arrived=FALSE
while (arrived == FALSE)
{
"work planned for processor to do while waiting for message data"
MPI_TEST(request,arrived,status)
}
"work planned for processor to do with the message data"
MPI_BUFFER_ATTACH und MPI_BUFFER_DETACH) for (i=0; i<n; ++i) {
MPI_Send(&a[k+i][l], m, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD);
}
p = &buffer;
for (i=k; i<k+n; ++i) {
for(j=l; j<l+m; ++j) {
*(p++) = a[i][j];
}
}
MPI_Send(p, n*m, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD)
MPI_PACK verwendet werden, das genau diese Aufgabe übernimmtcount = 0;
for(i=0; i<n; i++){
MPI_Pack(&a[k+i][l], m, MPI_DOUBLE, buffer, bufsize, count, MPI_COMM_WORLD);
}
MPI_Send(buffer, count, MPI_PACKED, dest, tag, MPI_COMM_WORLD);
MPI_UNPACK muss dann anstatt MPI_RECV zum Empfangen verwendet werden (mit MPI_PACK_SIZE kann die hierfür benötigte Größe des Puffers ermittelt werden)MPI_PACK verwendet wurde, man könnte sie also ganz "normal" z.B. als Double empfangenint MPI_Barrier ( MPI_Comm comm ) synchronisiert Prozesse ohne Daten zu übertragen; evtl. Overhead, daher sparsam verwendenint MPI_Bcast ( void* buffer, int count, MPI_Datatype datatype, int rank, MPI_Comm comm ) schickt Daten vom Rootprozess an alle anderen #include <mpi.h>
void main(int argc, char *argv[]) {
int rank;
double param;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
if(rank==5) param=23.0;
MPI_Bcast(¶m,1,MPI_DOUBLE,5,MPI_COMM_WORLD);
printf("P:%d after broadcast parameter is %f \n",rank,param);
MPI_Finalize();
}
int MPI_Reduce ( void* send_buffer, void* recv_buffer, int count, MPI_Datatype datatype, MPI_Op operation, int rank, MPI_Comm comm ) : sammelt Daten von den Prozessen ein, reduziert diese Daten auf einen Wert, speichert den reduzierten Wert im Rootprozesscount, datatype, rank müssen in allen Prozessen gleich seinoperation wird auf den Werten durchgeführt (sum, min, max etc.)#include <stdio.h>
#include <mpi.h>
void main(int argc, char *argv[])
{
int rank;
int source,result,root;
/* run on 10 processors */
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
root=7;
source=rank+1;
MPI_Barrier(MPI_COMM_WORLD);
MPI_Reduce(&source,&result,1,MPI_INT,MPI_PROD,root,MPI_COMM_WORLD);
if(rank==root) printf("P:%d MPI_PROD result is %d \n",rank,result);
MPI_Finalize();
}
int MPI_Gather ( void* send_buffer, int send_count, MPI_datatype send_type, void* recv_buffer, int recv_count, MPI_Datatype recv_type, int rank, MPI_Comm comm ) sammelt Daten von allen Prozessen im Rootprozess#include <stdio.h>
#include <mpi.h>
void main(int argc, char *argv[])
{
int rank,size;
double param[16],mine;
int sndcnt,rcvcnt;
int i;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
sndcnt=1;
mine=23.0+rank;
if(rank==7) rcvcnt=1;
MPI_Gather(&mine,sndcnt,MPI_DOUBLE,param,rcvcnt,MPI_DOUBLE,7,MPI_COMM_WORLD);
if(rank==7)
for(i=0;i<size;++i) printf("PE:%d param[%d] is %f \n",rank,i,param[i]]);
MPI_Finalize();
}
MPI_ALLGATHER macht das gleiche wie MPI_GATHER und anschließend direkt ein MPI_BCAST → Daten werden direkt an alle Prozesse verteiltint MPI_Scatter ( void* send_buffer, int send_count, MPI_datatype send_type, void* recv_buffer, int recv_count, MPI_Datatype recv_type, int rank, MPI_Comm comm ) sendet Daten vom Rootprozess an alle Prozesse abhängig vom Rank#include <stdio.h>
#include <mpi.h>
void main(int argc, char *argv[]) {
int rank,size,i;
double param[8],mine;
int sndcnt,rcvcnt;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
rcvcnt=1;
if(rank==3) {
for(i=0;i<8;++i) param[i]=23.0+i;
sndcnt=1;
}
MPI_Scatter(param,sndcnt,MPI_DOUBLE,&mine,rcvcnt,MPI_DOUBLE,3,MPI_COMM_WORLD);
for(i=0;i<size;++i) {
if(rank==i) printf("P:%d mine is %f n",rank,mine);
fflush(stdout);
MPI_Barrier(MPI_COMM_WORLD);
}
MPI_Finalize();
}
MPI_COMM_WORLD enthält alle ProzesseMPI_Comm_split), duplizieren (MPI_Comm_dup) vorhandener Intrakommunikatoren, erzeugen einer neuen Gruppe aus Prozessen, neu anordnen von Prozessen einer GruppeMPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm) spaltet einen Kommunikator in Subkommunikatorenkey, wenn identisch nach Rang in comm MPI_Comm_group(MPI_Comm comm, MPI_Group *group) extrahiert das Handle einer Prozessgruppe aus einem KommunikatorMPI_Group_incl(MPI_Group group, int n, int *rank, MPI_Group *newgroup) erzeugt eine neue Gruppe aus den in rank angegebenen Prozessenrank Prozesse angegeben, die nicht in der Gruppe group sind, bricht MPI mit einem Fehler ab, ebenso bei doppelten Einträgenn 0 ist, ist die neue Gruppe MPI_EMPTY_GROUPMPI_Group_excl hat die gleiche Syntax und erzeugt eine Gruppe mit den Prozessen außer den in rank angegebenenrank ist unerheblich für die neuen Ranks in newgroupn 0 ist, ist die neue Gruppe gleich der alten MPI_Group_union(MPI_Group group1, MPI_Group group2, MPI_Group *newgroup), MPI_Group_intersection und MPI_Group_difference erzeugt zwei Gruppen eine neue durch Anwendung der entsprechenden MengenoperationMPI_Group_size(MPI_Group group, int *size)MPI_Group_rank(MPI_Group group, int *rank)MPI_UNDEFINED wenn aufrufender Prozess nicht zur Gruppe gehörtMPI_group_translate_ranks(MPI_Group group1, int n, int *rank1, MPI_Group group2, int *rank2)MPI_Group_compare(MPI_Group group1, MPI_Group group2, int *result)result: MPI_IDENT, MPI_SIMILAR oder MPI_UNEQUALMPI_Group_free(MPI_Group *group) zerstört eine GruppeMPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newcomm) erzeugt einen neuen Kommunikator auf Basis einer GruppeMPI_COMM_NULL als RückgabewertMPI_Comm_free(MPI_Comm *comm) zerstört einen Kommunikator