Программирование для многопроцессорных систем в стандарте MPI - Шпаковский Г.И., Серикова Н.В.. Программирование для многопроцессорных систем в стандарте MPI -. Организация вычислений в многопроцессорных системах
Скачать 1.61 Mb.
|
Задание 4.17. #include #include #include "mpi.h" #define maxn 12 /* В этом примере сетка 12 x 12, 4 процесса */ int main( argc, argv ) int argc; char **argv; { int rank, value, size, errcnt, toterr, i, j, itcnt, i_first, i_last; MPI_Status status; double diffnorm, gdiffnorm, xlocal[(12/4)+2][12], xnew[(12/3)+2][12], x[maxn][maxn]; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_size( MPI_COMM_WORLD, &size ); if (size != 4) MPI_Abort( MPI_COMM_WORLD, 1 ); /* xlocal[][0] – нижние теневые точки, xlocal[][maxn+2] - верхние */ /* заполняем данные из файла */ if (rank == 0) { FILE *fp; fp =fopen( "in.dat", "r" ); if (!fp) MPI_Abort( MPI_COMM_WORLD, 1 ); /* заполняем все внутренние точки и граничные */ for (i=maxn-1; i>=0; i--) 302 { for (j=0; j } MPI_Scatter( x[0], maxn * (maxn/size), MPI_DOUBLE, xlocal[1], maxn * (maxn/size), MPI_DOUBLE, 0, МPI_COMM_WORLD ); /* В первом и последних процессах на одну строку меньше внутренних точек */ i_first = 1; i_last = maxn/size; if (rank == 0) i_first++; if (rank == size - 1) i_last--; itcnt = 0; do { /* передаем вверх, получаем снизу*/ if (rank < size - 1) MPI_Send( xlocal[maxn/size], maxn, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD ); if (rank > 0) MPI_Recv( xlocal[0], maxn, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, &status ); /* передаем вниз, получаем сверху*/ if (rank > 0) MPI_Send( xlocal[1], maxn, MPI_DOUBLE, rank - 1, 1,МPI_COMM_WORLD ); if (rank < size - 1) MPI_Recv( xlocal[maxn/size+1], maxn, MPI_DOUBLE, rank + 1, 1, MPI_COMM_WORLD, &status ); /* Вычисляем новые значения ( не на границах) */ itcnt ++; diffnorm = 0.0; for (i=i_first; i<=i_last; i++) for (j=1; j } /* присваиваем новые значения внутренним точкам */ for (i=i_first; i<=i_last; i++) for (j=1; j MPI_COMM_WORLD); gdiffnorm = sqrt( gdiffnorm ); if (rank == 0) printf( "At iteration %d, diff is %e\n", itcnt, gdiffnorm ); } while (gdiffnorm > 1.0e-2 && itcnt < 100); /* собираем данные в x и печатаем */ MPI_Gather( xlocal[1], maxn * (maxn/size), MPI_DOUBLE, x, maxn * (maxn/size), MPI_DOUBLE, 0, MPI_COMM_WORLD ); if (rank == 0) { printf( "Final solution is\n" ); for (i=maxn-1; i>=0; i--) { 303 for (j=0; j } MPI_Finalize( ); return 0; } Задание 4.20. #include #include #include #include { int iGatherSize=0, iRoot=0, iMyRank, i, j; int sendarray[100][150], *RBuffer=0; int *displs=0, *rcounts=0, stride = 255/*>100*/; MPI_Comm _Comm = MPI_COMM_WORLD; /* в группе все процессы */ MPI_Datatype stype; MPI_Init(&argc, &argv); MPI_Comm_rank(_Comm, &iMyRank); /* Главному процессу нужно выделить память для буфера */ if (iMyRank == iRoot) { MPI_Comm_size(_Comm, &iGatherSize); RBuffer = (int*)malloc(stride*iGatherSize*sizeof(int)); displs = (int*)malloc(iGatherSize * sizeof(int)); rcounts = (int*)malloc(iGatherSize * sizeof(int)); for (i = 0; i < iGatherSize; ++i) { displs[i] = stride * i;rcounts[i] = 100; } } srand((int)(MPI_Wtime()*1e4)); for (j = 0; j < 100; ++j) for (i = 0; i < 150; ++i) sendarray[j][i] = rand() % 999; MPI_Type_vector(100, 1, 150, MPI_INT, &stype); MPI_Type_commit(&stype); /* сбор данных */ MPI_Gatherv(sendarray,1,stype,RBuffer,rcounts,displs,MPI_INT,iRoot, _Comm); /* выведем данные на экран (выводятся только главном процессе, в остальных iGatherSize == 0) */ for (i = 0; i < iGatherSize; ++i) { printf("Process %i retuned:\n",i); for (j = 0; j < 100; ++j) printf("%4i ", RBuffer[i*stride + j]); printf("\n"); } 304 if (iMyRank == iRoot) { free(RBuffer); free(displs); free(rcounts);} MPI_Finalize(); return 0; } Задание 4.21. #include #include #include #include #define LEN 1000 int main(int argc, char* argv[]) { int iRoot=0, iMyRank, iSize =0, i; double dVal[LEN]; MPI_Comm _Comm = MPI_COMM_WORLD; /* в группе все процессы */ struct { double value; int index; } In, Out; MPI_Init(&argc, &argv); MPI_Comm_rank(_Comm, &iMyRank); MPI_Comm_size(_Comm, &iSize); srand((int)(MPI_Wtime()*1e4)); for (i = 0; i < LEN; ++i) { dVal[i] = rand() * (double)((double)rand() / ((unsigned)rand()+3)); printf("%4.2f ", dVal[i]); } /* выбор локального минимума */ In.value = dVal[0]; In.index = 0; for (i = 1; i < LEN; ++i) if (In.value < dVal[i]) { In.value = dVal[i]; In.index = i; } In.index += iMyRank*LEN; MPI_Reduce(&In, &Out, 1, MPI_DOUBLE_INT, MPI_MAXLOC, iRoot, _Comm); if (iMyRank == iRoot) printf("\n\nMaximum is %f, found in process %i with index %i\n", Out.value, Out.index / LEN, Out.index % LEN); MPI_Finalize(); } Задание 5.2. #include #include "mpi.h" int main( argc, argv ) int argc; char **argv; { int rank, size; 305 MPI_Comm new_comm; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_split( MPI_COMM_WORLD, rank == 0, 0, &new_comm ); if (rank == 0) master_io( MPI_COMM_WORLD, new_comm ); else slave_io( MPI_COMM_WORLD, new_comm ); MPI_Finalize( ); return 0; } /* подпрограмма master */ int master_io( master_comm, comm ) MPI_Comm comm; { int i,j, size; char buf[256]; MPI_Status status; MPI_Comm_size( master_comm, &size ); for (j=1; j<=2; j++) { for (i=1; i } } } /* подпрограмма slave */ int slave_io( master_comm, comm ) MPI_Comm comm; { char buf[256]; int rank; MPI_Comm_rank( comm, &rank ); sprintf( buf, "Hello from slave %d\n", rank ); MPI_Send( buf, strlen(buf) + 1, MPI_CHAR, 0, 0, master_comm ); sprintf( buf, "Goodbye from slave %d\n", rank ); MPI_Send( buf, strlen(buf) + 1, MPI_CHAR, 0, 0, master_comm ); return 0; } Задание 5.4. #include #include "mpi.h" #include "mpe.h" #define CHUNKSIZE 1000 #define REQUEST 1 #define REPLY 2 int main.( int argc, char *argv[] ) { int in, out, i, iters, max, ix, iy, ranks [1], done, temp,iter; double x, y, Pi, error, epsilon; 306 int numprocs,myid, server, totalin, totalout, workerid, rands [CHUNKSIZE] , request; MPI_Comm world, workers; MPI_Group world_group, worker_group; MPI_Status status; MPI_Init(&rgc,&argv); world = MPI_COMM_WORLD; MPI_Comm_size(world,&numprocs); MPI_Comm_rank (world, &myid); server = numprocs-1; /* последний процесс – сервер */ if (myid == 0) sscanf( argv[l], “%f”, &epsilon ); MPI_Bcast( &epsilon, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD ); /* создание нового коммуникатора */ MPI_Comm_group( world, &world_group ); ranks [0] = server; MPI_Group_excl( world_group, 1, ranks, &worker_group ); MPI_Comm_create( world, worker_group, &workers ); MPI_Group_free(&worker_group); if (myid == 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 ); } else /* рабочий процесс */ { request = 1; done = in = out = 0; max = INT_MAX; 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; у = (((double) rands [i++]) /max) * 2 - 1; if (x*x + y*y < 1.0) in++; else out++; } 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); 307 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); } } } if (myid == 0) { printf( "\npoints: %d\nin: %d, out: %d, } MPI_Comm_free(&workers); MPI_Finalize(); } Задание 6.1. #include #include "mpi.h" int main( argc, argv ) int argc; char **argv; { int rank, value, size, false=0, right_nbr, left_nbr; MPI_Comm ring_comm; MPI_Status status; MPI_Init( &argc, &argv ); MPI_Comm_size( MPI_COMM_WORLD, &size ); MPI_Cart_create( MPI_COMM_WORLD, 1, &size, &false, 1, &ring_comm ); MPI_Cart_shift( ring_comm, 0, 1, &left_nbr, &right_nbr ); MPI_Comm_rank( ring_comm, &rank ); MPI_Comm_size( ring_comm, &size ); do { if (rank == 0) { scanf( "%d", &value ); MPI_Send( &value, 1, MPI_INT, right_nbr, 0, ring_comm ); } else { MPI_Recv( &value, 1, MPI_INT, left_nbr, 0, ring_comm, &status ); MPI_Send( &value, 1, MPI_INT, right_nbr, 0, ring_comm ); 308 } printf( "Process %d got %d\n", rank, value ); } while (value >= 0); MPI_Finalize( ); return 0; } Задание 6.2. #include "mpi.h" #include #include #include { int i,j; for (j = 0; j < cnt; j++) { for (i = 0; i < size; i++) databuf[i] = sqrt(sqrt(databuf[i])); } } int main( argc, argv ) int argc; char **argv; { int rank, size, left_nbr, right_nbr, false = 0, true = 1, i, k, n, m, args[2]; double *rbuf, *sbuf, *databuf, t_comm, t_compute, t_both, t1; MPI_Comm comm; MPI_Request r_recv, r_send, r[2]; MPI_Status status, statuses[2]; MPI_Init( &argc, &argv ); /* получаем n и m */ MPI_Comm_rank( MPI_COMM_WORLD, &rank ); if (rank == 0) { args[0] = 20000; args[1] = 20000; for (i=0; i { args[0] = atoi( argv[i+1] ); i++; } else if (strcmp( argv[i], "-m" ) == 0) { args[1] = atoi( argv[i+1] ); i++; } } } MPI_Bcast( args, 2, MPI_INT, 0, MPI_COMM_WORLD ); n = args[0]; m = args[1]; 309 /* создаем новый коммуникатор и получаем соседей */ MPI_Comm_size( MPI_COMM_WORLD, &size ); MPI_Cart_create( MPI_COMM_WORLD, 1, &size, &false, true, &comm ); MPI_Cart_shift( comm, 0, 1, &left_nbr, &right_nbr ); MPI_Comm_size( comm, &size ); MPI_Comm_rank( comm, &rank ); rbuf = (double *) malloc( n * sizeof(double) ); sbuf = (double *) malloc( n * sizeof(double) ); databuf = (double *)malloc( m * sizeof(double) ); if (!rbuf || !sbuf) { fprintf( stderr, "Unable to allocate buffers of size %n\n", n ); MPI_Abort( MPI_COMM_WORLD, 1 ); } if (!databuf) { fprintf( stderr, "Unable to allocate buffers of size %n\n", m ); MPI_Abort( MPI_COMM_WORLD, 1 ); } for (k=0; k Compute( 1, m, databuf ); t1 = MPI_Wtime(); Compute( 1, m, databuf ); t_compute= MPI_Wtime() - t1; /* для сравнения время Irecv/Isend/Wait без вычислений */ MPI_Barrier( comm ); t1 = MPI_Wtime(); MPI_Irecv( rbuf, n, MPI_DOUBLE, left_nbr, 5, comm, &r[0] ); MPI_Isend( sbuf, n, MPI_DOUBLE, right_nbr, 5, comm, &r[1] ); MPI_Waitall( 2, r, statuses ); t_comm = MPI_Wtime() - t1; /* совмещаем вычисления и передачи */ MPI_Barrier( comm ); t1 = MPI_Wtime(); r_recv = MPI_REQUEST_NULL; for (k=0;k<3;k++) { /* ожидаем предыдущий recv */ MPI_Wait( &r_recv, &status ); MPI_Irecv( rbuf, n, MPI_DOUBLE, left_nbr, k, comm, &r_recv ); MPI_Isend( sbuf, n, MPI_DOUBLE, right_nbr, k, comm, &r_send ); Compute( 1, m, databuf ); MPI_Wait( &r_send, &status ); } MPI_Wait( &r_recv, &status ); t_both = MPI_Wtime() - t1; t_both /= 3.0; if (rank == 0) { printf( "For n = %d, m = %d, T_comm = %f, T_compute = %f, sum = %f, 310 T_both = %f\n", n, m, t_comm, t_compute, t_comm + t_compute, t_both ); } MPI_Finalize( ); return 0; } Задание 7.1. #include "mpi.h" #include #include { return n*i+j; } void main(int argc, char *argv[]) { int myid, numprocs, i, j,numsent,x, *buffer, *a, *b, *c, master,sender,anstype, ans; double startwtime, endwtime, t_calc,t_send; int cols,rows,row,max_cols,max_rows; MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myid); master = 0; if (myid==master) { printf("max_cols="); scanf("%d",&max_cols); /* задаем размерности */ printf("max_rows="); scanf("%d",&max_rows); } /* пересылаем всем процессам размерности матрицы */ MPI_Bcast(&max_cols,1,MPI_INT,master,MPI_COMM_WORLD); MPI_Bcast(&max_rows,1,MPI_INT,master,MPI_COMM_WORLD); rows = max_rows; cols = max_cols; t_calc = 0; t_send = 0; if (myid==master) { a=(int*) malloc(max_cols*max_rows*sizeof(int)); /* выделяем память */ buffer=(int*) malloc(max_cols*sizeof(int)); b=(int*) malloc(max_cols*sizeof(int)); c=(int*) malloc(max_rows*sizeof(int)); /* инициализируем матрицу и вектор*/ for (j=0;j /* пересылаем вектор всем процессам */ MPI_Bcast(b,cols,MPI_INT,master,MPI_COMM_WORLD); 311 if (numprocs-1 } for(i=0;i MPI_Recv(&ans,1,MPI_INT,MPI_ANY_SOURCE,MPI_ANY_TAG, MPI_COMM_WORLD,&status); sender = status.MPI_SOURCE; anstype =status.MPI_TAG; c[anstype]=ans; if (numsent } else /* признак конца работы */ MPI_Send(MPI_BOTTOM,0,MPI_INT,sender,999,MPI_COMM_WORLD); } endwtime=MPI_Wtime(); t_send=t_send+(endwtime-startwtime); /* результаты */ printf("\n c="); for (i=0;i { /* выделяем память */ buffer=(int*) malloc(max_cols*sizeof(int)); b=(int*) malloc(max_cols*sizeof(int)); /* получаем вектор b*/ MPI_Bcast(b,cols,MPI_INT,master,MPI_COMM_WORLD); again_sycle: /* получаем строку матрицы а*/ MPI_Recv(buffer,cols,MPI_INT,master,MPI_ANY_TAG,MPI_COMM_WORLD, &status); if(status.MPI_TAG==999) goto end_program; else { row =status.MPI_TAG; ans=0; /* считаем результат */ for (i=0;i 312 MPI_Send(&ans,1,MPI_INT,master,row,MPI_COMM_WORLD); goto again_sycle; } } end_program: MPI_Finalize(); } Задание 7.2. #include "mpi.h" #include #include { return n*i+j; } void main(int argc, char *argv[]) { int myid, numprocs, i, j,numsent,x,row, master,sender,anstype, ans; int *buffera, *bufferc, *a, *b, *c, colsa,rowsa,colsb,rowsb; double startwtime, endwtime, t_send; MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myid); master = 0; if (myid==master) { printf("cols a ="); scanf("%d",&colsa); /* задаем размерности a*/ printf(" rows a ="); scanf("%d",&rowsa); printf("cols b ="); scanf("%d",&colsb); /* задаем размерности b*/ printf(" rows b ="); scanf("%d",&rowsb); if (colsa != rowsb) MPI_Abort( MPI_COMM_WORLD, 1 ); } /* пересылаем всем процессам размерности матрицы */ MPI_Bcast(&colsa,1,MPI_INT,master,MPI_COMM_WORLD); MPI_Bcast(&rowsa,1,MPI_INT,master,MPI_COMM_WORLD); MPI_Bcast(&colsb,1,MPI_INT,master,MPI_COMM_WORLD); rowsb=colsa; if (myid==master) { a=(int*) malloc(colsa*rowsa*sizeof(int)); /* выделяем память */ b=(int*) malloc(rowsb*colsb*sizeof(int)); c=(int*) malloc(rowsa*colsb*sizeof(int)); buffera=(int*) malloc(colsa*sizeof(int)); bufferc=(int*) malloc(colsb*sizeof(int)); /* инициализируем матрицы*/ for (j=0;j 313 for (i=0;i } for(i=0;i MPI_Recv(bufferc,colsb,MPI_INT,MPI_ANY_SOURCE,MPI_ANY_TAG, MPI_COMM_WORLD,&status); sender = status.MPI_SOURCE; anstype =status.MPI_TAG; for (j=0;j } else /* признак конца работы */ MPI_Send(MPI_BOTTOM,0,MPI_INT,sender,999,MPI_COMM_WORLD); } endwtime=MPI_Wtime(); t_send=endwtime-startwtime; printf("\n c="); for (i=0;i } else /* некорневые процессы */ { /* выделяем память */ buffera=(int*) malloc(colsa*sizeof(int)); bufferc=(int*) malloc(colsb*sizeof(int)); b=(int*) malloc(colsb*rowsb*sizeof(int)); /* получаем b*/ 314 for (i=0;i /* получаем строку матрицы а*/ MPI_Recv(buffera,colsa,MPI_INT,master,MPI_ANY_TAG, MPI_COMM_WORLD,&status); if(status.MPI_TAG==999) goto end_program; else { row =status.MPI_TAG; /* считаем результат */ for (i=0;i /* отправляем результат */ MPI_Send(bufferc,colsb,MPI_INT,master,row,MPI_COMM_WORLD); goto again_sycle; } } end_program: MPI_Finalize(); } |