
Программирование для многопроцессорных систем в стандарте MPI - Шпаковский Г.И., Серикова Н.В
..pdf{ 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 <stdio.h> #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 );
291
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 <stdio.h> #include <stdlib.h> #include <malloc.h> #include <mpi.h>
int main(int argc, char* argv[])
{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; |
|
}
292
Задание 4.3.
#include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <mpi.h> #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)
293
{ printf("Result is:\n");
for (i = 0; i < n; ++i) printf("%3.0f ", dResult[i]);
}
MPI_Finalize(); return 0;
}
Задание 4.5.
#include <stdio.h> #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 <stdio.h> #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 );
294
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 <stdio.h> |
|
|
|
#include <stdlib.h> |
|
||
#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<NUMBER_OF_TESTS; k++)
{MPI_Barrier( MPI_COMM_WORLD ); d_in = 1.0;
t1 = MPI_Wtime(); for (j=0; j<nloop; j++)
MPI_Allreduce( &d_in, &d_out, 1, MPI_DOUBLE, MPI_SUM,
295
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 <stdio.h> #include <stdlib.h> #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<NUMBER_OF_TESTS; k++)
{MPI_Barrier( MPI_COMM_WORLD ); t1 = MPI_Wtime();
for (j=0; j<nloop; j++)
MPI_Barrier( MPI_COMM_WORLD );
t2 = (MPI_Wtime() - t1) / nloop; if (t2 < tmin) tmin = t2;
}
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 ); 296
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<size; r++) { if (rank == 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 <stdio.h> #include "mpi.h"
#define maxn 12 /* В этом примере сетка 12 x 12, 4 процесса */ int main( argc, argv )
297
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<maxn; j++) xlocal[i][j] = rank; for (j=0; j<maxn; j++)
{ xlocal[0][j] = -1; xlocal[maxn/size+1][j] = -1; }
/* передаем - вверх, получаем - снизу используем 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<maxn; j++) if (xlocal[i][j] != rank) errcnt++; for (j=0; j<maxn; j++)
{if (xlocal[0][j] != rank - 1) errcnt++;
if (rank < size-1 && xlocal[maxn/size+1][j] != rank + 1) errcnt++;
}
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;
}
298
Задание 4.14.
#include <stdio.h> #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<maxn; j++) xlocal[i][j] = rank; for (j=0; j<maxn; j++)
{xlocal[0][j] = -1; xlocal[maxn/size+1][j] = -1;
}
/* Передаем и получаем от нижних процессов.
Используем 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<maxn; j++) if (xlocal[i][j] != rank) errcnt++; for (j=0; j<maxn; j++)
{if (xlocal[0][j] != rank - 1) errcnt++;
if (rank < size-1 && xlocal[maxn/size+1][j] != rank + 1) errcnt++;
}
MPI_Reduce( &errcnt, &toterr, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD );
if (rank == 0) |
{ |
if (toterr) |
printf( "! found %d errors\n", toterr ); |
|
299 |
else printf( "No errors\n" );
}
MPI_Finalize( ); return 0;
}
Задание 4.16.
#include <stdio.h> |
|
|
#include <math.h> |
|
|
#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<maxn; j++) xlocal[i][j] = rank; |
|
for (j=0; j<maxn; j++) |
||
{ |
xlocal[i_first-1][j] = -1; |
|
} |
xlocal[i_last+1][j] = -1; |
|
|
|
|
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)
300