Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование для многопроцессорных систем в стандарте MPI - Шпаковский Г.И., Серикова Н.В

..pdf
Скачиваний:
240
Добавлен:
24.05.2014
Размер:
1.69 Mб
Скачать

if (numprocs-1<rows) x=numprocs-1; else x=rows;

for (i=0;i<x;i++)

{ for (j=0;j<cols;j++) buffer[j]=a[f(i,j,cols)]; /* посылка строки матрицы а */ MPI_Send(buffer,cols,MPI_INT,i+1,i,MPI_COMM_WORLD); numsent=numsent+1;

}

for(i=0;i<rows;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<rows)

{ for (j=0;j<cols;j++) buffer[j]=a[f(numsent,j,cols)]; MPI_Send(buffer,cols,MPI_INT,sender,numsent,MPI_COMM_WORLD); numsent=numsent+1;

}

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<rows;i++) printf(" %d ",c[i]); printf("\n"); printf("send & handle time = %f\n",t_send);

}

 

else

/* не корневые процессы */

{

/* выделяем память */

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<cols;i++) ans=ans+buffer[i]*b[i];

/* отправляем результат */

311

MPI_Send(&ans,1,MPI_INT,master,row,MPI_COMM_WORLD); goto again_sycle;

}

}

end_program: MPI_Finalize();

}

Задание 7.2.

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

int f(int i,int j,int n) /* функция обращения к элементу i,j матрицы */ { 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<colsa;j++)

312

 

for (i=0;i<rowsa;i++)

a[f(i,j,colsa)]=j+1;

 

 

for (j=0;j<colsb;j++)

 

 

 

for (i=0;i<rowsb;i++)

b[f(i,j,colsb)]=j+1;

 

numsent=0;

 

 

startwtime=MPI_Wtime();

/* пересылаем матрицу b всем процессам */

for (i=0;i<rowsb;i++)

 

 

 

MPI_Bcast(&b[f(i,0,colsb)],colsb,MPI_INT,master,MPI_COMM_WORLD);

if (numprocs-1<rowsa)

x=numprocs-1;

 

else x=rowsa;

 

 

for (i=0;i<x;i++)

 

 

{

for (j=0;j<colsa;j++) buffera[j]=a[f(i,j,colsa)];

/* посылка строки матрицы а */

 

MPI_Send(buffera,colsa,MPI_INT,i+1,i,MPI_COMM_WORLD);

}

numsent=numsent+1;

 

 

 

 

 

for(i=0;i<rowsa;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<colsb;j++) c[f(anstype,j,colsb)]=bufferc[j];

 

if (numsent<rowsa)

 

 

{for (j=0;j<colsa;j++) buffera[j]=a[f(numsent,j,colsa)];

MPI_Send(buffera,colsa,MPI_INT,sender,numsent,MPI_COMM_WORLD); numsent=numsent+1;

}

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<rowsa;i++)

{ for (j=0;j<colsb;j++) printf(" %d ",c[f(i,j,colsb)]); printf("\n");

}

printf("send & handle time = %f\n",t_send);

}

 

else

/* некорневые процессы */

{

/* выделяем память */

buffera=(int*) malloc(colsa*sizeof(int)); bufferc=(int*) malloc(colsb*sizeof(int)); b=(int*) malloc(colsb*rowsb*sizeof(int));

/* получаем b*/ 313

for (i=0;i<colsb;i++)

for (i=0;i<rowsb;i++) MPI_Bcast(&b[f(i,0,colsb)],colsb,MPI_INT,master,MPI_COMM_WORLD);

again_sycle:

/* получаем строку матрицы а*/ 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;

/* считаем результат */

{bufferc[i]=0;

for (j=0;j<colsa;j++) bufferc[i]=bufferc[i]+buffera[j]*b[f(j,i,colsb)];

}

/* отправляем результат */ MPI_Send(bufferc,colsb,MPI_INT,master,row,MPI_COMM_WORLD); goto again_sycle;

}

}

end_program: MPI_Finalize();

}

Задание 8.1.

#include <stdio.h>

 

#include <stdlib.h>

 

#include <math.h>

 

#include "mpi.h"

 

#include "jacobi.h"

/* описание Mesh как структуры */

static int do_print = 0;

 

static int max_it = 100;

 

int main( argc, argv )

 

int argc;

 

 

char **argv;

 

{ int

rank, size, i, j, itcnt, maxm, maxn, lrow, k;

Mesh

mesh;

 

double

diffnorm, gdiffnorm, *swap,t, *xlocalrow, *xnewrow;

MPI_Init( &argc, &argv );

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

Get_command_line( rank, argc, argv, &maxm, &maxn, &do_print, &max_it );

Setup_mesh( maxm, maxn, &mesh );

 

for (k=0; k<2; k++)

 

{ itcnt = 0;

 

Init_mesh( &mesh );

/* инициализация */

 

314

MPI_Barrier( mesh.ring_comm ); t = MPI_Wtime();

if (do_print && rank == 0)

printf( "Starting at time %f\n", t ); fflush(stdout);

lrow = mesh.lrow;

 

 

do

 

 

 

{ Exchange( &mesh );

 

/* заполнение теневых точек */

itcnt ++;

diffnorm

= 0.0;

xnewrow = mesh.xnew

+ 1 * maxm;

xlocalrow = mesh.xlocal + 1 * maxm;

 

/*

вычисляем новые значения (не на границах) */

for (i=1; i<=lrow; i++)

 

 

{ for (j=1; j<maxm-1; j++)

{ double diff;

/* умножаем на 0.25 вместо деления на 4.0 */

xnewrow[j] = (xlocalrow[j+1] + xlocalrow[j-1] +

 

xlocalrow[maxm + j] + xlocalrow[-maxm + j]) * 0.25;

diff

= xnewrow[j] - xlocalrow[j];

diffnorm += diff * diff;

}

 

 

 

xnewrow

+= maxm;

 

xlocalrow += maxm;

}

swap = mesh.xlocal; mesh.xlocal = mesh.xnew; mesh.xnew = swap;

 

 

 

/* точность вычислений */

MPI_Allreduce( &diffnorm, &gdiffnorm, 1, MPI_DOUBLE, MPI_SUM,

mesh.ring_comm ); gdiffnorm = sqrt( gdiffnorm );

if (do_print && rank == 0)

{ printf( "At iteration %d, diff is %e\n", itcnt, gdiffnorm ); fflush( stdout );

}

} while (gdiffnorm > 1.0e-2 && itcnt < max_it); t = MPI_Wtime() - t;

}

if (rank == 0)

{ printf( "%s: %d iterations in %f secs (%f MFlops), m=%d n=%d np=%d\n", TESTNAME, itcnt, t, itcnt * (maxm-2.0)*(maxn-2)*(4)*1.0e-6/t, maxm, maxn, size);

}

MPI_Comm_free( &mesh.ring_comm ); MPI_Finalize( );

return 0;

}

#include <stdio.h> #include <stdlib.h> #include <math.h> #include "mpi.h"

315

#include "jacobi.h"

/* процедура для получение размеров сетки из командной строки */ void Get_command_line( rank, argc, argv, maxm, maxn, do_print, maxit )

int rank, argc, *maxm, *maxn, *do_print, *maxit;

char **argv;

 

{ int args[4], i;

 

if (rank == 0)

/* получение maxn из командной строки */

{*maxn = DEFAULT_MAXN; *maxm = -1;

for (i=1; i<argc; i++)

{if (!argv[i]) continue;

if (strcmp( argv[i], "-print" ) == 0) *do_print = 1; else

if (strcmp( argv[i], "-n" ) == 0)

{ *maxn = atoi( argv[i+1] );

i++;

}

else

 

 

if (strcmp( argv[i], "-m" ) == 0)

 

 

{ *maxm = atoi( argv[i+1] );

i++;

}

else

 

 

if (strcmp( argv[i], "-maxit" ) == 0)

 

{ *maxit = atoi( argv[i+1] );

i++;

}

}

 

 

if (*maxm < 0) *maxm = *maxn;

 

 

args[0] = *maxn;

 

 

args[1] = *maxm; args[2] = *do_print;

args[3] = *maxit;

}

MPI_Bcast( args, 4, MPI_INT, 0, MPI_COMM_WORLD );

*maxn = args[0];

*maxm

= args[1];

*do_print = args[2];

*maxit

= args[3];

}

#include <stdio.h> #include <stdlib.h> #include <math.h> #include "mpi.h"

#include "jacobi.h"

/* процедура размещения элементов сетки по процессам */ void Setup_mesh( maxm, maxn, mesh )

int maxm, maxn; Mesh *mesh;

{ int false = 0; int true = 1; int lrow, rank, size;

register double *xlocal, *xnew;

/* картезианская топология */ MPI_Comm_size( MPI_COMM_WORLD, &size );

MPI_Cart_create( MPI_COMM_WORLD,1,&size,&false,true,&mesh->ring_comm );

316

/* определяем соседей*/ MPI_Cart_shift( mesh->ring_comm, 0, 1, &mesh->down_nbr, &mesh->up_nbr ); MPI_Comm_rank( mesh->ring_comm, &rank );

MPI_Comm_size( mesh->ring_comm, &size ); lrow = (maxn - 2) / size;

if (rank < ((maxn - 2) % size)) lrow++; mesh->lrow = lrow;

mesh->maxm = maxm; mesh->maxn = maxn;

/* размещение частей сетки по процессам */ mesh->xlocal = xlocal = (double *)malloc( maxm * ( lrow + 2 ) * sizeof(double) ); mesh->xnew = xnew = (double *)malloc( maxm * ( lrow + 2 ) * sizeof(double) ); if (!mesh->xlocal || !mesh->xnew)

{ fprintf( stderr, "Unable to allocate local mesh\n" ); MPI_Abort( MPI_COMM_WORLD, 1 );

}

}

 

 

 

void Init_mesh( mesh )

/* процедура инициализации сетки */

Mesh *mesh;

 

 

{

 

 

 

int i, j, lrow, rank, maxm;

 

 

register double *xlocal, *xnew;

 

 

xlocal = mesh->xlocal;

 

 

xnew

= mesh->xnew;

 

 

lrow

= mesh->lrow;

 

 

maxm

= mesh->maxm;

 

 

MPI_Comm_rank( mesh->ring_comm, &rank );

 

for (i=1; i<=lrow; i++)

 

 

for (j=0; j<maxm; j++)

 

 

{ xlocal[i*maxm+j] = rank;

xnew[i*maxm+j] = rank;

}

 

 

/* заполнение граничных значений */

for (j=0; j<maxm; j++)

{ xlocal[j] = -1; xlocal[(lrow+1)*maxm + j] = rank + 1; xnew[j] = -1; xnew[(lrow+1)*maxm + j] = rank + 1;

}

for (i=1; i<=lrow; i++)

{ xnew[i*maxm] = rank; xnew[i*maxm+maxm-1] = rank;

}

}

#include <stdio.h> #include <stdlib.h> #include <math.h> #include "mpi.h"

317

#include "jacobi.h"

 

void Exchange( mesh )

/* процедура обменов для заполнения теневых то-

чек */

 

 

 

 

Mesh *mesh;

 

 

 

{ MPI_Status status;

 

double *xlocal

= mesh->xlocal;

int

maxm

 

= mesh->maxm;

int

lrow

= mesh->lrow;

 

int

up_nbr

 

= mesh->up_nbr;

int

down_nbr

= mesh->down_nbr;

MPI_Comm ring_comm = mesh->ring_comm;

/* передаем вверх, получаем снизу */ MPI_Send( xlocal + maxm * lrow, maxm, MPI_DOUBLE, up_nbr, 0, ring_comm ); MPI_Recv( xlocal, maxm, MPI_DOUBLE, down_nbr, 0, ring_comm, &status );

/* передаем вниз, получаем сверху */ MPI_Send( xlocal + maxm, maxm, MPI_DOUBLE, down_nbr, 1, ring_comm ); MPI_Recv( xlocal + maxm * (lrow + 1), maxm, MPI_DOUBLE, up_nbr, 1,

ring_comm, &status );

}

318

ИСТОЧНИКИ И НФОРМАЦИИ

1.Argonne National Laboratory (http://www.mcs.anl.gov/mpi ).

2.Кластерные установки в России

( http://parallel.ru/parallel/russia/russian_clusters.html ).

3. Научно-исследовательский вычислительный центр МГУ

( http://www.parallel.ru).

4. Gropp W., Lusk E., Skjellum A. Using MPI: Portable Parallel Programming with the Message-Passing Interface. Second edition, published in 1999 by MIT Press, 371 p.

5.Snir M., Otto S., Huss-Lederman S. etc. MPI – The Complete Reference: Vol.1, The MPI Core. Second edition, published in 1998 by MIT Press, 426 p.

6.Gropp W., .Huss-Lederman S., Lumsdaine A. etc. MPI – The Complete Reference: Vol.2, The MPI-2 Extensions. Published in 1998 by MIT Press.

7.Gropp W., Lusk E., Thakur R. Using MPI - 2: advanced features of the messagepassing interface. Published in 1999 by MIT Press, 382 p.

8.Peter S. Pacheco. Parallel Programming With MPI. Published by Morgan Kaufmann, San Francisco, California, 1997.

9.Программа Союзного государства СКИФ по разработке кластерных сис-

тем, 2001 г. (http://www.botik.ru ).

10.Шпаковский Г.И., Серикова Н.В. Пособие по программированию для многопроцессорных систем в среде MPI. Мн., 2001г. (http://www.bsu.by).

11.MPI: Стандарт интерфейса передачи сообщений. Перевод с англ. Шпаков-

ского Г.И., Мн., 2001 г. ( http://www.bsu.by ).

12.Белорусский государственный университет (http://www.bsu.by ).

13.Шпаковский Г.И. Организация параллельных ЭВМ и суперскалярных процессоров: Учеб. пособие. Мн.: Белгосуниверситет, 1996. 284 с.

14.Кузюрин Н.Н., Фрумкин М.А. Параллельные вычисления: теория и алгоритмы // Программирование. 1991. N 2. С. 3–19.

15.Bacon D.F., Grahem S.L., Sharp O.J. Compiler transformations for high performance computing // ASM Computing Surveys. 1994. V. 26. № 4.

16.Корнеев В.В. Параллельные вычислительные системы. М.: “Нолидж”, 1999. 320 с.

17.Буза М.К. Введение в архитектуру компьютеров: Учеб. пособие. Мн.:

БГУ, 2000. 253 с.

18.Андреев А.Н. Что такое OpenMP?

( http://parallel.ru/tech/tech_dev/openmp.html ).

19.User’s Guide for MPE (unix.mcs.anl.gov/mpi/mpich/docs/mpeguide).

20.MPI: A Message – Passing Interface Standart. June 12, 1995 (http://www.mcs.anl.gov/mpi ).

21.Ортега Д., Пул У. Введение в численные методы решения дифференциальных уравнений. М., 1986.

22.Математические основы криптологии: Учеб. пособие / Харин Ю.С., Берник В.И., Матвеев Г.В. Мн.: БГУ, 1999. 319 с.

23.Молдовян А.А., Молдовян Н.А., Советов Б.Я. Криптография. СПб.:Из–во

“Лань”, 2001. 224с.

319

24.Мулярчик С.Г. Численные методы: Конспект лекций. Мн., БГУ, 2001. 127с.

25.Самарский А.А., Гулис А.В. Численные методы. М., 1989.

26.Параллельный отладчик TotalView (http://www.etnus.com).

27.Производительность кластеров: http://parallel.ru/cluster/performance.html.

28.Библиотеки BLAS, LAPACK, BLACS, ScaLAPACK: (http://www.netlib.org).

29.Дацюк В.Н., Букатов А.А., Жегуло А.И. Многопроцессорные системы и параллельное программирование. Метод. пособие, части 1,2,3 (http://rsusu1.rnd.runnet.ru/ncube/koi8/method/m1/context.html ).

30.PETSc: http://www-fp.mcs.anl.gov/petsc/index.html.

320

Соседние файлы в предмете Программирование