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

Реализация алгоритма

// инициализация матриц
void InitializationMatrix(double* MatrixA, double* MatrixB, int Size)
{
 for (int i = 0; i < Size; i++)
  for (int j = 0; j < Size; j++)
  {
   MatrixA[i*Size+j] = rand()/double(100);
   MatrixB[i*Size+j] = rand()/double(100);
  }
}


void Scatter(double* Matrix, double* MatrixBlock, int Size, int BSize)
{
  double* MatrixRow = new double [BSize*Size];

  if (GridC[1] == 0)  MPI_Scatter(Matrix, BSize*Size, MPI_DOUBLE, MatrixRow, BSize*Size, MPI_DOUBLE, 0, ColComm);

  for (int i = 0; i < BSize; i++)
  MPI_Scatter(&MatrixRow[i*Size], BSize, MPI_DOUBLE, &(MatrixBlock[i*BSize]), BSize, MPI_DOUBLE, 0, RowComm);
 
  delete [] MatrixRow;
}

// разделение данных на блоки  для умножения
void Distribution(double* MatrixA, double* MatrixB, double* Block, double* BlockB, int Size, int BSize)
{
 Scatter(MatrixA, Block, Size, BSize);
 Scatter(MatrixB, BlockB, Size, BSize);
}

// создание решетки
void CreateGird()
{
 int DimSize[2]; 
 int Periodic[2];
 int Subdims[2]; 
 
 DimSize[0] = Grid;
 DimSize[1] = Grid;
 Periodic[0] = 0;
 Periodic[1] = 0;

 MPI_Cart_create(MPI_COMM_WORLD, 2, DimSize, Periodic, 1, &GridComm);

 MPI_Cart_coords(GridComm, Rank, 2, GridC);
 
 Subdims[0] = 0; 
 Subdims[1] = 1; 
 
 MPI_Cart_sub(GridComm, Subdims, &RowComm);
 
    Subdims[0] = 1;
    Subdims[1] = 0;
 
 MPI_Cart_sub(GridComm, Subdims, &ColComm);
}

void BlockAComm(int i, double *BlockA, double* Block, int BSize)
{
 int tmp = (GridC[0] + i) % Grid;
 
 if (GridC[1] == tmp)
 {
  for (int j = 0; j < BSize*BSize; j++) BlockA[j] = Block[j];
 }
 
 MPI_Bcast(BlockA, BSize*BSize, MPI_DOUBLE, tmp, RowComm);
}

void BlockBComm(double *BlockB, int BSize)
{
 MPI_Status Status;
 int Next = GridC[0] + 1;
 if (GridC[0] == Grid - 1) Next = 0;
 int Prev = GridC[0] - 1;
 if (GridC[0] == 0) Prev = Grid - 1;

 MPI_Sendrecv_replace(BlockB, BSize*BSize, MPI_DOUBLE, Next, 0, Prev, 0, ColComm, &Status);
}

// последовательное перемножение матриц

void Mult(double* MatrixA, double* MatrixB, double* MatrixR, int Size)
{
  int i,j,k;   
  for (i = 0; i < Size; i++) 
    for (j = 0; j < Size; j++)
      for (k = 0; k < Size; k++)
        MatrixR[i*Size+j] += MatrixA[i*Size+k]*MatrixB[k*Size+j];
}

// метод Фокса

void Method(double* BlockA, double* Block, double* BlockB, double* BlockR, int BSize)
{
 for (int i = 0; i < Grid; i++)
 {
  BlockAComm(i, BlockA, Block, BSize);
  Mult(BlockA, BlockB, BlockR, BSize);
  BlockBComm(BlockB, BSize);
 }
}

// соединение данных

void CollectionResult(double *Result, double* BlockR, int Size, int BSize)
{
  double *Row = new double [Size*BSize];

  for (int i = 0; i < BSize; i++) MPI_Gather( &BlockR[i*BSize], BSize, MPI_DOUBLE, &Row[i*Size], BSize, MPI_DOUBLE, 0, RowComm);
 
  if (GridC[1] == 0) MPI_Gather(Row, BSize*Size, MPI_DOUBLE, Result, BSize*Size, MPI_DOUBLE, 0, ColComm);
  delete []Row;
}

int main(int argc, char* argv[])
{
 double *MatrixA = NULL, *BlockA = NULL; // матрица №1
 double *MatrixB = NULL, *BlockB = NULL; // матрица №2
 double *Result = NULL, *BlockR = NULL; // результат
 double *Block = NULL;
 int Size,BSize; // размер пространства

 double t1,t2;

 MPI_Init(&argc, &argv);
 
 MPI_Comm_size(MPI_COMM_WORLD, &Count);
 MPI_Comm_rank(MPI_COMM_WORLD, &Rank);

 Grid = sqrt((double)Count);

 if (Count != Grid*Grid) { if (Rank == 0) printf("Xren\n"); }
 else
 {
  if (Rank == 0) printf("Matrix multiplication: \n");

  CreateGird();

  if (Rank == 0)
  {
   do
   {
    printf("Enter size: ");
    scanf("%d", &Size);
 
    if (Size%Grid != 0) printf ("...\n");
   }
   while (Size%Grid != 0);
  }

  MPI_Bcast(&Size, 1, MPI_INT, 0, MPI_COMM_WORLD);

  BSize = Size / Grid;

  BlockA = new double [BSize*BSize];
  BlockB = new double [BSize*BSize];
  BlockR = new double [BSize*BSize];
  Block = new double [BSize*BSize];

  for (int i =0; i < BSize*BSize; i++) BlockR[i] = 0;

  if (Rank == 0)
  {
   MatrixA = new double [Size*Size];
   MatrixB = new double [Size*Size];
   Result = new double [Size*Size];
   InitializationMatrix(MatrixA, MatrixB, Size);
  }

  t1 = MPI_Wtime();

  Distribution(MatrixA,MatrixB,Block,BlockB,Size,BSize);

  Method(BlockA, Block, BlockB, BlockR, BSize);

  CollectionResult(Result, BlockR, Size, BSize);

  t2 = MPI_Wtime();

  if (Rank == 0) printf("Parallel method: %f\n",t2-t1);

  t1 = MPI_Wtime();

  Mult(MatrixA, MatrixB, Result, Size);

  t2 = MPI_Wtime();

  if (Rank == 0) printf("Sequential method: %f\n",t2-t1);

  delete[] MatrixA;
  delete[] MatrixB;
  delete[] Result; 
  delete[] BlockA;
  delete[] BlockB;
  delete[] BlockR;
 }

 MPI_Finalize();

 _getch();

 return 0;
}

Новости

22.10.2012
04.09.2012
05.04.2012
06.03.2012
02.03.2012