Коллективные взаимодействия процессов

35
Коллективные взаимодействия процессов

description

Коллективные взаимодействия процессов. Коллективные взаимодействия процессов. MPI предоставляет ряд функций для коллективного взаимодейстия процессов. Эти функции называют коллективными, поскольку они должны вызываться одновременно на всех - PowerPoint PPT Presentation

Transcript of Коллективные взаимодействия процессов

Page 1: Коллективные взаимодействия процессов

Коллективные взаимодействия процессов

Page 2: Коллективные взаимодействия процессов

Коллективные взаимодействия процессов

MPI предоставляет ряд функций для коллективного взаимодейстия процессов.

Эти функции называют коллективными, поскольку они должны вызываться одновременно на всех процессах, принадлежащих некоторому коммуникатору.

Page 3: Коллективные взаимодействия процессов

int MPI_Bcast ( buffer, count, datatype, root, comm )

void* buffer - начальный адрес буфера для передачи собщенийint count - число передаваемых элементов данныхMPI_Datatype datatype - тип передаваемых данныхint root - ранг процесса, посылающего данныеMPI_Comm comm - коммуникатор

Page 4: Коллективные взаимодействия процессов

int MPI_Reduce ( sendbuf, recvbuf, count, datatype, op, root, comm )

void *sendbuf; буфер операндовvoid *recvbuf; буфер приемаint count; число данныхMPI_Datatype datatype; тип данныхMPI_Op op; операцияint root; ранг процесса, содержащего результатMPI_Comm comm; коммуникатор

op

Page 5: Коллективные взаимодействия процессов

MPI_MAX максимум

MPI_MIN минимум MPI_SUM сумма

MPI_PROD произведение MPI_LAND логическое "и"

MPI_BAND побитовое "и"

MPI_LOR логическое "или"

MPI_BOR побитовое "или"

MPI_LXOR логическое исключающее "или"

MPI_BXOR побитовое исключающее "или"

Page 6: Коллективные взаимодействия процессов

Вычисление числа Пи

1

021

4

x

12 3

41

23

41

23

4 1

Page 7: Коллективные взаимодействия процессов

Вычисление числа Pi

#include "mpi.h" #include <math.h> int main(argc,argv) int argc; char *argv[]; { int done = 0, n, myid, numprocs, i, rc; double PI25DT = 3.141592653589793238462643; double mypi, pi, h, sum, x, a; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myid);

Page 8: Коллективные взаимодействия процессов

while (!done) { if (myid == 0) { printf("Enter the number of intervals: (0 quits) "); scanf("%d",&n); } MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); if (n == 0) break; h = 1.0 / (double) n; sum = 0.0; for (i = myid + 1; i <= n; i += numprocs) { x = h * ((double)i - 0.5); sum += 4.0 / (1.0 + x*x); } mypi = h * sum;

Page 9: Коллективные взаимодействия процессов

MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (myid == 0) printf("pi is approximately %.16f, Error is %.16f\n", pi, fabs(pi - PI25DT)); } MPI_Finalize(); }

Page 10: Коллективные взаимодействия процессов

Функция синхронизации процессов:

int MPI_Barrier ( comm ) ;

MPI_Comm comm;

Page 11: Коллективные взаимодействия процессов

int MPI_Scatter ( sendbuf, sendcnt, sendtype, recvbuf, recvcnt, recvtype, root, comm )

void *sendbuf;int sendcnt;MPI_Datatype sendtype;void *recvbuf;int recvcnt;MPI_Datatype recvtype;int root;MPI_Comm comm;

0

12

3

Page 12: Коллективные взаимодействия процессов

0

12

3

int MPI_Gather ( sendbuf, sendcnt, sendtype, recvbuf, recvcount, recvtype, root, comm ) void *sendbuf; int sendcnt; MPI_Datatype sendtype; void *recvbuf; int recvcount; MPI_Datatype recvtype; int root; MPI_Comm comm;

Page 13: Коллективные взаимодействия процессов

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

#define N 5

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

int* dta;int ldta;int i;int size;int rank;MPI_Comm comm;

MPI_Init(&argc, &argv);comm = MPI_COMM_WORLD;

MPI_Comm_size(comm, &size);MPI_Comm_rank(comm, &rank);

if(rank == 0) {dta = (int*) calloc(size, sizeof(int));

}

Page 14: Коллективные взаимодействия процессов

for(i = 0; i < N; i ++) {int j;

MPI_Scatter(dta, 1, MPI_INT, &ldta, 1, MPI_INT, 0, comm);

ldta += rank;MPI_Gather(&ldta, 1, MPI_INT, dta, 1,

MPI_INT, 0, comm);

if(rank == 0) {for(j = 0; j < size; j ++)

printf("[%d]", dta[j]);printf("\n");fflush(stdout);

}}

MPI_Finalize();}

Page 15: Коллективные взаимодействия процессов

int MPI_Allreduce ( sendbuf, recvbuf, count, datatype, op, comm )

void *sendbuf;void *recvbuf;int count;MPI_Datatype datatype;MPI_Op op;MPI_Comm comm;

int MPI_Allgather ( sendbuf, sendcount, sendtype,recvbuf, recvcount, recvtype, comm )

void *sendbuf;int sendcount;MPI_Datatype sendtype;void *recvbuf;int recvcount;MPI_Datatype recvtype;MPI_Comm comm;

Page 16: Коллективные взаимодействия процессов

int MPI_Alltoall( sendbuf, sendcount, sendtype, recvbuf, recvcnt, recvtype, comm )

void *sendbuf;int sendcount;MPI_Datatype sendtype;void *recvbuf;int recvcnt;MPI_Datatype recvtype;MPI_Comm comm;

Page 17: Коллективные взаимодействия процессов

#include <stdio.h>#include <mpi.h>#define N 5

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

int* sdta;int* rdta;int i;int size;int rank;MPI_Comm comm;

MPI_Init(&argc, &argv);comm = MPI_COMM_WORLD;

MPI_Comm_size(comm, &size);MPI_Comm_rank(comm, &rank);

sdta = (int*) malloc(sizeof(int) * size);rdta = (int*) malloc(sizeof(int) * size);

for(i = 0; i < size; i ++) sdta[i] = i;

Page 18: Коллективные взаимодействия процессов

for(i = 0; i < N; i ++) { int j;

MPI_Alltoall(sdta, 1, MPI_INT, rdta, 1, MPI_INT, comm);

for(j = 0; j < size; j ++) sdta[j] = rdta[j];if(rank == 0) {

printf("[");for(j = 0; j < size; j ++) printf(" %d", sdta[j]);

printf("]\n");fflush(stdout);

}

}

MPI_Finalize();}

Page 19: Коллективные взаимодействия процессов

Группы и коммуникаторы

Page 20: Коллективные взаимодействия процессов

Интер- и интра-коммуникаторы

Интра-коммуникаторы

Интер-коммуникатор

Интра-коммуникаторы объединяют процессы из одной группы.

Интер-коммуникаторпозволяет передавать данные между процессами из разных интра-коммуникаторов.

Интер-коммуникаторы не могут использоваться в коллективных взаимодействиях.

01

2

3

4

1

0

3

2

1

1

Page 21: Коллективные взаимодействия процессов

Группы и коммуникаторы

Совокупности MPI-процессов образуют группы.

Понятие ранга процесса имеет смысл только по отношению к определенной группе или коммуникатору.

Каждому интра-коммуникатору соответствует группа процессов. По группе процессов можно построить коммуникатор.

Page 22: Коллективные взаимодействия процессов

Получение группы процессов по коммуникатору:

int MPI_Comm_group ( comm, group )

MPI_Comm comm; MPI_Group *group;

Создание коммуникатора по группе процессов:

int MPI_Comm_create ( comm, group, comm_out )

MPI_Comm comm; “старый” коммуникатор

MPI_Group group; группа процессов

MPI_Comm *comm_out; новый коммуникатор

Page 23: Коллективные взаимодействия процессов

int MPI_Group_excl ( group, n, ranks, newgroup )

MPI_Group group, *newgroup;

int n, *ranks;

int MPI_Group_incl ( group, n, ranks, group_out )

MPI_Group group, *group_out;

int n, *ranks;

Page 24: Коллективные взаимодействия процессов

int MPI_Group_intersection ( group1, group2, group_out )

int MPI_Group_union ( group1, group2, group_out )

int MPI_Group_difference ( group1, group2, group_out )

MPI_Group group1, group2, *group_out;

Page 25: Коллективные взаимодействия процессов

Создание и удаление интра-коммуникаторов

Получение дубликата коммуникатора:

int MPI_Comm_dup(MPI_Comm comm, MPI_Comm* newcomm)

Разбиение коммуникатора на несколько:

int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm* newcomm)

comm – «старый коммуникатор»

color – селектор коммуникатора

key – задает порядок на создаваемых коммуникаторах

newcomm – создаваемый коммуникатор

Удаление коммуникатора:

int MPI_Comm_free(MPI_Comm* comm)

Page 26: Коллективные взаимодействия процессов

Вычисление числа Pi методом Монте-Карло

Из книги Gropp, Lusk, Skjellum

Page 27: Коллективные взаимодействия процессов

Схема вычислений

server

workerprocesses

коммуникаторworkers

коммуникаторworld

Page 28: Коллективные взаимодействия процессов

/* compute pi using Monte Carlo method */#include <math.h>#include "mpi.h"

#define CHUNKSIZE 1000#define INT_MAX 1000000000/* message tags */#define REQUEST 1#define REPLY 2int main( int argc, char *argv[] ){ int iter; int in, out, i, iters, max, ix, iy, ranks[1], done, temp; double x, y, Pi, error, epsilon; int numprocs, myid, server, totalin, totalout, workerid; int rands[CHUNKSIZE], request; MPI_Comm world, workers; MPI_Group world_group, worker_group; MPI_Status status;

MPI_Init(&argc,&argv); world = MPI_COMM_WORLD; MPI_Comm_size(world,&numprocs); MPI_Comm_rank(world,&myid);

Page 29: Коллективные взаимодействия процессов

if (myid == server) { /* I am the rand server */do { MPI_Recv(&request, 1, MPI_INT, MPI_ANY_SOURCE, REQUEST, world, &status);

if (request) {for (i = 0; i < CHUNKSIZE; i++) rands[i] = random();MPI_Send(rands, CHUNKSIZE, MPI_INT,

status.MPI_SOURCE, REPLY, world);}

} while( request>0 ); }

Page 30: Коллективные взаимодействия процессов

else { /* I am a worker process */ request = 1; done = in = out = 0; max = INT_MAX; /* max int, for normalization */ MPI_Send( &request, 1, MPI_INT, server, REQUEST, world ); MPI_Comm_rank( workers, &workerid ); iter = 0; while (!done) { iter++;

request = 1; MPI_Recv( rands, CHUNKSIZE, MPI_INT, server, REPLY, world, &status ); for (i=0; i<CHUNKSIZE; ) { x = (((double) rands[i++])/max) * 2 - 1; y = (((double) rands[i++])/max) * 2 - 1; if (x*x + y*y < 1.0) in++; else out++; }

Page 31: Коллективные взаимодействия процессов

MPI_Allreduce(&in, &totalin, 1, MPI_INT, MPI_SUM, workers);

MPI_Allreduce(&out, &totalout, 1, MPI_INT, MPI_SUM, workers);

Pi = (4.0*totalin)/(totalin + totalout); error = fabs( Pi-3.141592653589793238462643); done = (error < epsilon || (totalin+totalout) > 1000000); request = (done) ? 0 : 1; if (myid == 0) {

printf( "\rpi = %23.20f", Pi );MPI_Send( &request, 1, MPI_INT, server, REQUEST,

world ); } else {

if (request) MPI_Send(&request, 1, MPI_INT, server, REQUEST,

world); }}

}

Page 32: Коллективные взаимодействия процессов

if (myid == 0) { printf( "\npoints: %d\nin: %d, out: %d, <ret> to exit\n",

totalin+totalout, totalin, totalout );getchar();

} MPI_Comm_free(&workers); MPI_Finalize();}

Page 33: Коллективные взаимодействия процессов

Создание интер-коммуникаторов

int MPI_Intercomm_create(MPI_Comm local_comm, int local_leader, MPI_Comm peer_comm, int remote_leader, int tag, MPI_Comm* new_comm)

local_comm – коммуникатор, которому принадлежит вызывающий процесс

local_leader – ранг некоторого процесса в немpeer_comm – коммуникатор, которому принадлежат процессы local_leader и remote_leader (часто COMM_WORLD)tag – используется для взаимодействия между local_leader и remote_leader (целесообразно проверять уникальность)new_comm – построенный интер-коммуникатор

Page 34: Коллективные взаимодействия процессов

#include <mpi.h>

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

int color;int rank;int m;MPI_Comm comm;MPI_Comm icomm;MPI_Status st;

MPI_Init(&argc, &argv);MPI_Comm_rank(MPI_COMM_WORLD, &rank);color = rank % 2;

MPI_Comm_split(MPI_COMM_WORLD, color, rank, &comm);if(color == 0)

MPI_Intercomm_create(comm, 0, MPI_COMM_WORLD, 1, 10, &icomm);

elseMPI_Intercomm_create(comm, 0, MPI_COMM_WORLD,

0, 10, &icomm);

Page 35: Коллективные взаимодействия процессов

if(color == 0) {

int lrank;

MPI_Comm_rank(comm, &lrank);

MPI_Send(&lrank, 1, MPI_INT, lrank, 0, icomm);

}

else {

int lrank;

MPI_Comm_rank(comm, &lrank);

MPI_Recv(&m, 1, MPI_INT, lrank, 0, icomm, &st);

}

printf("rank = %d, m = %d\n", rank, m);

MPI_Finalize();

}