Программирование для многопроцессорных систем в стандарте MPI - Шпаковский Г.И., Серикова Н.В.. Программирование для многопроцессорных систем в стандарте MPI -. Организация вычислений в многопроцессорных системах
Скачать 1.61 Mb.
|
Задание 3.15. /* пересылка вектора из 1000 элементов типа MPI_DOUBLE со страйдом 24 между элементами. Самостоятельная упаковка и распаковка (не используем типы данных MPI) */ #include #include #include "mpi.h" #define NUMBER_OF_TESTS 10 int main( argc, argv ) int argc; char **argv; { MPI_Datatype vec1, vec_n, old_types[2]; MPI_Aint indices[2]; double *buf, *lbuf, t1, t2, tmin; register double *in_p, *out_p; int i, j, k, nloop, rank, n, stride, blocklens[2]; MPI_Status status; 289 MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); n = 1000; stride = 24; nloop = 100000/n; buf = (double *) malloc( n * stride * sizeof(double) ); if (!buf) { fprintf( stderr, "Could not allocate send/recv buffer of size %d\n",n * stride ); MPI_Abort( MPI_COMM_WORLD, 1 ); } lbuf = (double *) malloc( n * sizeof(double) ); if (!lbuf) { fprintf( stderr, "Could not allocated send/recv lbuffer of size %d\n", n ); MPI_Abort( MPI_COMM_WORLD, 1 ); } if (rank == 0) printf( "Kind\tn\tstride\ttime (sec)\tRate (MB/sec)\n" ); tmin = 1000; for (k=0; k MPI_Sendrecv( MPI_BOTTOM, 0, MPI_INT, 1, 14, MPI_BOTTOM, 0, MPI_INT, 1, 14, MPI_COMM_WORLD, &status ); t1 = MPI_Wtime(); for (j=0; j MPI_Recv( lbuf, n, MPI_DOUBLE, 1, k, MPI_COMM_WORLD, &status ); for (i=0; i } else if (rank == 1) { /* убедимся, что оба процесса готовы к приему/передаче */ MPI_Sendrecv( MPI_BOTTOM, 0, MPI_INT, 0, 14, MPI_BOTTOM, 0, MPI_INT, 0, 14, MPI_COMM_WORLD, &status ); for (j=0; j } } } tmin = tmin / 2.0; 290 if (rank == 0) printf( "User\t%d\t%d\t%f\t%f\n",n,stride,tmin, n *sizeof(double)*1.0e-6 / tmin ); MPI_Finalize( ); return 0; } Задание 3.18. #include #include #include #include #include { int iMyRank, i, gsize; MPI_Comm _Comm = MPI_COMM_WORLD; /* в группе все процессы */ MPI_Status status; double x[100][100][100], e[9][9][9]; int oneslice, twoslice, threeslice, sizeof_double; MPI_Init(&argc, &argv); MPI_Comm_size(_Comm, &gsize); MPI_Comm_rank(_Comm, &iMyRank); /* извлекаем секцию а(1-17-2, 3-11, 2-10) и записываем в е */ MPI_Type_extent(MPI_DOUBLE, &sizeof_double); MPI_Type_vector(9, 1, 2, MPI_DOUBLE, &oneslice); MPI_Type_hvector(9, 1, 100 * sizeof_double, oneslice, &twoslice); MPI_Type_hvector(9, 1, 100 * 100 * sizeof_double, twoslice, &threeslice); MPI_Type_commit(&threeslice); MPI_Sendrecv(&x[1][3][2], 1, threeslice, iMyRank, 0, e, 9*9*9, MPI_DOUBLE, iMyRank, 0, MPI_COMM_WORLD, &status); if (iMyRank == 0) { printf("x = ("); for (i = 0; i < 100; ++i) printf("%f", x[i]); printf(")"); } MPI_Finalize(); return 0; } Задание 3.19. #include #include #include #include #include #define MATRIXSIZE 10 int main(int argc, char* argv[]) 291 { int iMyRank, iRoot = 0, iRow, iColumn, gsize, sizeof_double; MPI_Comm _Comm = MPI_COMM_WORLD; /* в группе все процессы */ MPI_Status status; double x[MATRIXSIZE][MATRIXSIZE], y[MATRIXSIZE][MATRIXSIZE]; MPI_Init(&argc, &argv); MPI_Comm_size(_Comm, &gsize); MPI_Comm_rank(_Comm, &iMyRank); if (iMyRank == iRoot) { printf("Transpose the matrix\n"); srand((int)((double)MPI_Wtime()*1e7)); for (iRow = 0; iRow < MATRIXSIZE; ++iRow) { for (iColumn = 0; iColumn < MATRIXSIZE; ++iColumn) { x[iRow][iColumn] = rand() % 100; printf("%3.0f ", x[iRow][iColumn]); } printf("\n"); } } MPI_Type_extent(MPI_DOUBLE, &sizeof_double); MPI_Type_vector(MATRIXSIZE, 1, MATRIXSIZE, MPI_DOUBLE, &iRow); MPI_Type_hvector(MATRIXSIZE, 1, sizeof_double, iRow, &iColumn); MPI_Type_commit(&iColumn); MPI_Sendrecv(x, 1, iColumn, iMyRank, 0, y, MATRIXSIZE * MATRIXSIZE, MPI_DOUBLE, iMyRank, iRoot, MPI_COMM_WORLD, &status); if (iMyRank == iRoot) { for (iRow = 0; iRow < MATRIXSIZE; ++iRow) { printf("\n"); for (iColumn = 0; iColumn < MATRIXSIZE; ++iColumn) printf("%3.0f ", y[iRow][iColumn]); } } MPI_Finalize(); return 0; } Задание 4.1. #include #include "mpi.h" int main( argc, argv ) int argc; char **argv; { int rank, value; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); do { if (rank == 0) scanf( "%d", &value ); 292 MPI_Bcast( &value, 1, MPI_INT, 0, MPI_COMM_WORLD ); printf( "Process %d got %d\n", rank, value ); } while (value >= 0); MPI_Finalize( ); return 0; } Задание 4.2. #include #include #include #include { int iRoot=0, iMyRank, iSize =0, i; double dSum = 0, dResult = 0, Vec_1[20], Vec_2[20]; MPI_Comm _Comm = MPI_COMM_WORLD; /* в группе все процессы */ MPI_Init(&argc, &argv); MPI_Comm_rank(_Comm, &iMyRank); MPI_Comm_size(_Comm, &iSize); if ( iMyRank == iRoot ) { srand((int)(MPI_Wtime()*1e4)); /* заполнение векторов */ printf("Vector1=\n"); for (i = 0; i < 20; ++i) { Vec_1[i] = rand() % 11; printf("%3.0f ", Vec_1[i]); } printf("\nVector2=\n"); for (i = 0; i < 20; ++i) { Vec_2[i] = rand() % 11; printf("%3.0f ", Vec_2[i]); } printf("\n"); } MPI_Bcast(Vec_1, 20, MPI_DOUBLE, iRoot, _Comm); MPI_Bcast(Vec_2, 20, MPI_DOUBLE, iRoot, _Comm); /* считаем локальную сумму */ for (i = iMyRank, dSum = 0; i < 20; i += iSize) dSum += Vec_1[i] * Vec_2[i]; MPI_Reduce(&dSum, &dResult, 1, MPI_DOUBLE, MPI_SUM, iRoot, _Comm); if (iMyRank == iRoot) printf("Result is %f\n", dResult); MPI_Finalize(); return 0; } 293 Задание 4.3. #include #include #include #include #define n 10 #define m 5 int main(int argc, char* argv[]) { int iRoot=0, iMyRank, iSize =0, i, j; double dSum[n], dResult[n], Vec_1[m], Matr[m][n]; MPI_Comm _Comm = MPI_COMM_WORLD; /* в группе все процессы */ MPI_Init(&argc, &argv); MPI_Comm_rank(_Comm, &iMyRank); MPI_Comm_size(_Comm, &iSize); if ( iMyRank == iRoot ) { srand((int)(MPI_Wtime()*1e4)); /* заполнение векторов */ printf("Vector1=\n"); for (i = 0; i < m; ++i) { Vec_1[i] = rand() % 11; printf("%2.0f ", Vec_1[i]); } printf("\nMatrix=\n"); for (i = 0; i < m; ++i) { for (j = 0; j < n; ++j) { Matr[i][j] = rand() % 11; printf("%2.0f ", Matr[i][j]); } printf("\n"); } printf("\n"); } MPI_Bcast(Vec_1, m, MPI_DOUBLE, iRoot, _Comm); for (i = 0; i < n; ++i) MPI_Bcast(Matr[i], m, MPI_DOUBLE, iRoot, _Comm); /* считаем локальную сумму */ for (j = 0; j < n; ++j) { dSum[j] = 0; for (i = iMyRank; i < m; i += iSize) dSum[j] += Vec_1[i] * Matr[i][j]; } MPI_Reduce(&dSum, dResult, n, MPI_DOUBLE, MPI_SUM, iRoot, _Comm); if (iMyRank == iRoot) 294 { printf("Result is:\n"); for (i = 0; i < n; ++i) printf("%3.0f ", dResult[i]); } MPI_Finalize(); return 0; } Задание 4.5. #include #include "mpi.h" int main( argc, argv ) int argc; char **argv; { struct { int a; double b } value; MPI_Datatype mystruct, old_types[2]; int blocklens[2], rank; MPI_Aint indices[2]; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); blocklens[0] = 1; blocklens[1] = 1; /* базовые типы */ old_types[0] = MPI_INT; old_types[1] = MPI_DOUBLE; /* адреса каждого элемента */ MPI_Address( &value.a, &indices[0] ); MPI_Address( &value.b, &indices[1] ); indices[1] = indices[1] - indices[0]; indices[0] = 0; /*новый тип данных */ MPI_Type_struct( 2, blocklens, indices, old_types, &mystruct ); MPI_Type_commit( &mystruct ); do { if (rank == 0) scanf( "%d %lf", &value.a, &value.b ); MPI_Bcast( &value, 1, mystruct, 0, MPI_COMM_WORLD ); printf( "Process %d got %d and %lf\n", rank, value.a, value.b ); } while (value.a >= 0); MPI_Type_free( &mystruct ); MPI_Finalize( ); return 0; } Задание 4.6. #include #include "mpi.h" int main( argc, argv ) int argc; char **argv; { int rank, Packsize, position, a; double b; char Packbuf[100]; MPI_Init( &argc, &argv ); 295 MPI_Comm_rank( MPI_COMM_WORLD, &rank ); do { if (rank == 0) { scanf( "%d %lf", &a, &b ); Packsize = 0; MPI_Pack( &a, 1, MPI_INT, Packbuf, 100, &Packsize, MPI_COMM_WORLD ); MPI_Pack( &b, 1, MPI_DOUBLE, Packbuf, 100, &Packsize,MPI_COMM_WORLD); } MPI_Bcast( &Packsize, 1, MPI_INT, 0, MPI_COMM_WORLD ); MPI_Bcast( Packbuf, Packsize, MPI_PACKED, 0, MPI_COMM_WORLD ); if (rank != 0) { position = 0; MPI_UnPack( Packbuf, Packsize, &position, &a, 1, MPI_INT, MPI_COMM_WORLD ); MPI_UnPack( Packbuf, Packsize, &position, &b, 1, MPI_DOUBLE,MPI_COMM_WORLD ); } printf( "Process %d got %d and %lf\n", rank, a, b ); } while (a >= 0); MPI_Finalize( ); return 0; } Задание 4.8. #include #include #include "mpi.h" #define NUMBER_OF_TESTS 10 int main( argc, argv ) int argc; char **argv; { int rank, size, j, k, nloop; double t1, t2, tmin, d_in, d_out; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_size( MPI_COMM_WORLD, &size ); if (rank == 0 && size == 1) printf( "Kind\t\tnp\ttime (sec)\n" ); nloop = 1000; tmin = 1000; for (k=0; k 296 MPI_COMM_WORLD ); t2 = (MPI_Wtime() - t1) / nloop; if (t2 < tmin) tmin = t2; } if (rank == 0) printf( "Allreduce\t%d\t%f\n", size, tmin ); MPI_Finalize( ); return 0; } Задание 4.9. #include #include #include "mpi.h" #define NUMBER_OF_TESTS 10 int main( argc, argv ) int argc; char **argv; { double t1, t2, tmin; int j, k, nloop, rank, size; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_size( MPI_COMM_WORLD, &size ); if (rank == 0 && size == 1) printf( "Kind\tnp\ttime (sec)\n" ); nloop = 1000; tmin = 1000; for (k=0; k } if (rank == 0) printf( "Barrier\t%d\t%f\n", size, tmin ); MPI_Finalize( ); return 0; } Задание 4.11. int main( argc, argv ) int argc; char *argv[]; { double A[8][8], alocal[4][4]; int i, j, r, rank, size; MPI_Datatype stype, t[2], vtype; MPI_Aint displs[2]; int blklen[2], sendcount[4], sdispls[4]; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); 297 MPI_Comm_size( MPI_COMM_WORLD, &size ); if (size != 4) { fprintf( stderr, "This program requires exactly four processors\n" ); MPI_Abort( MPI_COMM_WORLD, 1 ); } if (rank == 0) { /* Инициализация матрицы */ for (j=0; j<8; j++) for (i=0; i<8; i++) A[i][j] = 1.0 + i / 10.0 + j / 100.0; /* новый векторный тип для подматриц */ MPI_Type_vector( 4, 4, 8, MPI_DOUBLE, &vtype ); t[0] = vtype; t[1] = MPI_UB; displs[0] = 0; displs[1] = 4 * sizeof(double); blklen[0] = 1; blklen[1] = 1; MPI_Type_struct( 2, blklen, displs, t, &stype ); MPI_Type_commit( &stype ); sendcount[0] = 1; sendcount[1] = 1; sendcount[2] = 1; sendcount[3] = 1; sdispls[0] = 0; sdispls[1] = 1; sdispls[2] = 8; sdispls[3] = 9; MPI_Scatterv( &A[0][0], sendcount, sdispls, stype, &alocal[0][0], 4*4, MPI_DOUBLE, 0, MPI_COMM_WORLD ); } else MPI_Scatterv( (void *)0, (void *)0, (void *)0, MPI_DATATYPE_NULL, &alocal[0][0], 4*4, MPI_DOUBLE, 0, MPI_COMM_WORLD ); /* каждый процесс печатает свою часть матрицы */ for (r = 0; r { printf( "Output for process %d\n", r ); for (j=0; j<4; j++) { for (i=0; i<4; i++) printf( "%.2f ", alocal[i][j] ); printf( "\n" ); } fflush( stdout ); } MPI_Barrier( MPI_COMM_WORLD ); } MPI_Finalize( ); return 0; } Задание 4.12. #include #include "mpi.h" #define maxn 12 /* В этом примере сетка 12 x 12, 4 процесса */ int main( argc, argv ) 298 int argc; char **argv; { int rank, value, size, errcnt, toterr, i, j; MPI_Status status; double x[12][12], xlocal[(12/4)+2][12]; 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] - верхние */ for (i=1; i<=maxn/size; i++) for (j=0; j /* передаем - вверх, получаем - снизу используем xlocal[i] вместо xlocal[i][0] */ 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, MPI_COMM_WORLD ); if (rank < size - 1) MPI_Recv( xlocal[maxn/size+1], maxn, MPI_DOUBLE, rank + 1, 1, MPI_COMM_WORLD, &status ); /* Проверяем на корректность результаты */ errcnt = 0; for (i=1; i<=maxn/size; i++) for (j=0; j } MPI_Reduce( &errcnt, &toterr, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD ); if (rank == 0) { if (toterr) printf( "! found %d errors\n", toterr ); else printf( "No errors\n" ); } MPI_Finalize( ); return 0; } 299 Задание 4.14. #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, up_nbr, down_nbr; MPI_Status status; double x[12][12],xlocal[(12/4)+2][12]; 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] - верхние */ for (i=1; i<=maxn/size; i++) for (j=0; j } /* Передаем и получаем от нижних процессов. Используем xlocal[i] вместо xlocal[i][0] */ up_nbr = rank + 1; if (up_nbr >= size) up_nbr = MPI_PROC_NULL; down_nbr = rank - 1; if (down_nbr < 0) down_nbr = MPI_PROC_NULL; MPI_Sendrecv( xlocal[maxn/size], maxn, MPI_DOUBLE, up_nbr, 0, xlocal[0], maxn, MPI_DOUBLE, down_nbr, 0, MPI_COMM_WORLD, &status ); /* Передаем и получаем от верхних процессов. */ MPI_Sendrecv( xlocal[1], maxn, MPI_DOUBLE, down_nbr, 1, xlocal[maxn/size+1], maxn, MPI_DOUBLE, up_nbr, 1, MPI_COMM_WORLD, &status ); /* Проверяем на корректность результаты */ errcnt = 0; for (i=1; i<=maxn/size; i++) for (j=0; j } MPI_Reduce( &errcnt, &toterr, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD ); if (rank == 0) { if (toterr) printf( "! found %d errors\n", toterr ); 300 else printf( "No errors\n" ); } MPI_Finalize( ); return 0; } Задание 4.16. #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]; 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] - верхние */ /* В первом и последних процессах на одну строку меньше внутренних точек */ i_first = 1; i_last = maxn/size; if (rank == 0) i_first++; if (rank == size - 1) i_last--; for (i=1; i<=maxn/size; i++) for (j=0; j } itcnt = 0; do { /* передаем вверх, получаем снизу, xlocal[i] вместо xlocal[i][0] */ 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, MPI_COMM_WORLD ); if (rank < size - 1) 301 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); MPI_Finalize( ); return 0; } |