Новости
О Центре
Кластер
Обучение
Основной курс по параллельному программированию
Учебные курсы
Магистратура
Дополнительное образование
Работы студентов
Библиотека
Исследования
Конференции
Полезные ссылки
NVIDIA
Контакты
О сайте
Имя:
Пароль:
запомнить:
Забыли пароль? Регистрация

Параллельный алгоритм

Из определения операции матричного умножения следует, что вычисление всех элементов матрицы С может быть выполнено независимо друг от друга. Как результат, возможный подход для организации параллельных вычислений состоит в использовании в качестве базовой подзадачи процедуры определения одного элемента результирующей матрицы С. Для проведения всех необходимых вычислений каждая подзадача должна содержать по одной строке матрицы А и одному столбцу матрицы В. Общее количество получаемых при таком подходе подзадач оказывается равным n2 (по числу элементов матрицы С).

Алгоритм представляет собой итерационную процедуру, количество итераций которой совпадает с числом подзадач. На каждой итерации алгоритма каждая подзадача содержит по одной строке матрицы А и одному столбцу матрицы В. При выполнении итерации проводится скалярное умножение содержащихся в подзадачах строк и столбцов, что приводит к получению соответствующих элементов результирующей матрицы С. По завершении вычислений в конце каждой итерации столбцы матрицы В должны быть переданы между подзадачами с тем, чтобы в каждой подзадаче оказались новые столбцы матрицы В и могли быть вычислены новые элементы матрицы C. При этом данная передача столбцов между подзадачами должна быть организована таким образом, чтобы после завершения итераций алгоритма в каждой подзадаче последовательно оказались все столбцы матрицы В.
Выделенные базовые подзадачи характеризуются одинаковой вычислительной трудоемкостью и равным объемом передаваемых данных. Когда размер матриц n оказывается больше, чем число процессоров p, базовые подзадачи можно укрупнить, объединив в рамках одной подзадачи несколько соседних строк и столбцов перемножаемых матриц. В этом случае исходная матрица A разбивается на ряд горизонтальных полос, а матрица B представляется в виде набора вертикальных полос. Размер полос при этом следует выбрать равным k=n/p (в предположении, что n кратно p), что позволит по-прежнему обеспечить равномерность распределения вычислительной нагрузки по процессорам, составляющим многопроцессорную вычислительную систему.

#include<stdafx.h>
#include<mpi.h>
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<math.h>
#include<time.h>
int ProcNum; 
int ProcRank;
int flag=0;
int Size;
 double *A;  double *B; double *C;

//***********************************************************
 void PrintMatrix(double* pMatrix,int Size) {
  for (int i=0;i<Size;i++) {printf("\n");
    for (int j=0;j<Size;j++)
   printf("%7.4f ",pMatrix[i*Size+j]);
  }
}
//------------------------------------------------------------
void RandInit (double* pMatrix, int Size) {
srand(100);
for (int i=0; i<Size; i++) {
  for (int j=0;j<Size;j++)  pMatrix[i*Size+j]=rand()/double(1000);
}
}
//-------------------------------------------------
void InitProcess (double* &A,double* &B,double* &C ,int &Size) {
MPI_Comm_size(MPI_COMM_WORLD, &ProcNum);
MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);
if (ProcRank == 0) {
  do {printf("\n--Square matrix multiplication--");
      printf("\nPlease, enter matrix size: "); scanf("%d", &Size);     
      if (Size< ProcNum) printf("Matrix size is less than the number of processes! \n");
      if (Size%ProcNum!=0) printf("Matrix size should be dividable by the number of processes! \n");
  }
  while ((Size< ProcNum)||(Size%ProcNum!=0));
  }
if (Size<10) flag=1;
MPI_Bcast(&Size, 1, MPI_INT, 0, MPI_COMM_WORLD);

if (ProcRank == 0) {
    A = new double [Size*Size];
    B = new double [Size*Size];
    C = new double [Size*Size];
    RandInit (A, Size); RandInit (B, Size);
 }
}
//-------------------------------------------------
void Flip (double *&B, int dim) {
double temp=0.0;
    for (int i=0; i<dim; i++){
  for (int j=i+1; j<dim; j++){
      temp=B[i*dim+j];B[i*dim+j]=B[j*dim+i];B[j*dim+i]=temp;
   }
  }
}
//-------------------------------------------------
void MatrixMultiplicationMPI(double *&A, double *&B, double *&C, int &Size) {
 int dim =Size;
 int i, j, k, p, ind;
 double temp;
 MPI_Status Status;
  int ProcPartSize=dim/ProcNum;
  int ProcPartElem=ProcPartSize*dim;
 double* bufA=new double[dim*ProcPartSize];
 double* bufB=new double[dim*ProcPartSize];
 double* bufC=new double[dim*ProcPartSize];
  int ProcPart = dim/ProcNum, part = ProcPart*dim;
 if (ProcRank == 0) {
  Flip(B,Size);
 }
 
  MPI_Scatter(A, part, MPI_DOUBLE, bufA, part, MPI_DOUBLE, 0, MPI_COMM_WORLD);
  MPI_Scatter(B, part, MPI_DOUBLE, bufB, part, MPI_DOUBLE, 0, MPI_COMM_WORLD);

 temp=0.0;
 for(i=0;i<ProcPartSize;i++){
        for(j=0;j<ProcPartSize; j++){
   for(k=0;k<dim;k++) temp+=bufA[i*dim+k]*bufB[j*dim+k];
   bufC[i*dim+j+ProcPartSize*ProcRank]=temp;temp=0.0;
  }
 }

  int NextProc; int PrevProc;
 for(p=1; p<ProcNum; p++) {
    NextProc = ProcRank+1;
    if ( ProcRank ==ProcNum-1 ) NextProc = 0;
    PrevProc = ProcRank - 1;
    if ( ProcRank == 0 ) PrevProc = ProcNum-1;
    MPI_Sendrecv_replace(bufB,part, MPI_DOUBLE, NextProc, 0, PrevProc, 0, MPI_COMM_WORLD, &Status);
   temp=0.0;
   for (i=0; i<ProcPartSize; i++) {
   for(j=0; j<ProcPartSize; j++) {
    for(k=0; k<dim; k++){
     temp +=bufA[i*dim+k]*bufB[j*dim+k];}
    if (ProcRank - p >= 0 )
     ind=ProcRank - p;
    else ind=(ProcNum - p+ProcRank);
    bufC[i*dim+j+ind*ProcPartSize]=temp;
    temp=0.0;
   }
  }
 }
 MPI_Gather(bufC, ProcPartElem, MPI_DOUBLE, C, ProcPartElem, MPI_DOUBLE, 0, MPI_COMM_WORLD);

 delete []bufA;
 delete []bufB;
 delete []bufC;
}

//--------------------------------------------------------

void main(int argc, char* argv[]) {
    double beg, end, serial, parallel=0;
    MPI_Init ( &argc, &argv );  
    InitProcess (A,B,C,Size);
    beg=MPI_Wtime();
    MatrixMultiplicationMPI(A,B,C,Size);
   end=MPI_Wtime(); parallel= end-beg; 
 if (ProcRank == 0) {
    printf("\n",&ProcNum);
     printf ("\n");
    printf("\nTime of execution -  Parallel calculation:\n");
    printf("%7.4f",parallel);
    if (flag) {
       printf("\nMatrix C - Parallel calculation\n");
       PrintMatrix(C,Size);
       }   
     }
      MPI_Finalize();
delete [] A; delete [] B; delete [] C;  
        getch();

}

Новости

22.10.2012
04.09.2012
05.04.2012
06.03.2012
02.03.2012