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

Программа

<


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

double *matrix, *vector, *result, *_matrix, *_vector, *_result, m=0.0;
//_matrix, _vector, _result - куски матрицы, вектора b и вектора x на определенном процессе
int  size=8, p=1, status, str_count; //str_count-число строк исходной матрицы, хранящихся на конкретном процессе
//status - статус решения задачи
//stringcount - количество строк на процессе
double  start, finish, deltime; // переменные для засечения времени 
int *IndexVedStr;    //массив номеров ведущих строк на каждой итерации // i-ая итерация - j-ая строка ведущая
int *IndexVedIter;   /* массив номеров итераций, на которых соответствующие строки системы, расположенные на процессе, выбраны  ведущими */

int ProcCount, ProcRank, *ui1,//-массив размером с количество процессов. каждый элемент
	                          //хранит индекс первого элемента из столбца свободных членов, который принадлежит процессу
	*range;  //массив с количествами пересылаемых элеметов из столбца свободных членов на каждый процесс 
//------------------------------------------------------------------------------

void StartProcInitialization()

{ 
   int show;
   printf("\nInput matrixix rank: ");
   scanf("%i", &size);
   //printf("\nInput srand argument: ");
   //scanf("%i", &p);
   printf("\nDo you want to see values?(1/0): ");
   scanf("%i", &show);
  //size=8;
  srand(p);
  //randomize();
 matrix = new double [size*size];
 vector = new double [size];
 result = new double [size];

 for(int i=0; i<size*size; i++)
 {
	 matrix[i]=rand();
	 if(show==1) printf("\nmatrix[%i]=%f", i, matrix[i]);
 };

 for(int i=0; i<size; i++)
 {
	 vector[i]=rand();
	 if(show==1) printf("\nb[%i]=%f", i, vector[i]);
	 result[i]=0;
 };
}

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

void ProcInitialization()

{
  int nstrings; //Число строк, ещё не распределённых по процессам 
  if (ProcRank == 0) 
	{
		printf("\nStarted!"); 
		StartProcInitialization();
    }                

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

 //Определение размера части данных, расположенных на конкретном процессе

 nstrings = size;

 for (int i=0; i<ProcRank; i++)
	nstrings = nstrings-nstrings/(ProcCount-i);

 str_count = nstrings/(ProcCount-ProcRank);
 _matrix = new double [str_count*size];//выделяем память под строки матрицы
 _vector = new double [str_count]; //память под элементы столбца свободных членов
 _result = new double [str_count]; //память под элементы вектора результата 
 IndexVedStr = new int [size]; //массив индексов ведущих строк системы на каждой итерации
 IndexVedIter = new int [str_count]; /* итерация, на которой соответствующая строка системы, расположенная на процессе, выбрана  ведущей */
 ui1 = new int [ProcCount];
 range = new int [ProcCount];

 for (int i=0; i<str_count; i++) 
	 IndexVedIter[i] = -1;
}

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

// Распределение исходных данных между процессами

void Distribution()
{
 int *firstsendindex;             //Индекс первого элемента матрицы, передаваемого процессу
 int *sendrange;            //Число элементов матрицы, передаваемых процессу
 int CountProcessstrings;    
 int nstrings;    
 firstsendindex = new int [ProcCount];
 sendrange = new int [ProcCount];

 nstrings = size;

for (int i=0; i<ProcCount; i++)  //Определяем, сколько элементов матрицы будет передано каждому процессу
{
 int Previoussize = (i==0) ? 0 : sendrange[i-1];

 int PreviousIndex = (i==0) ? 0 : firstsendindex[i-1];

 int Portion = (i==0) ? 0 : CountProcessstrings;             //число строк, отданных предыдущему процессу

 nstrings -= Portion;

 CountProcessstrings = nstrings/(ProcCount-i);

 sendrange[i] = CountProcessstrings*size;

 firstsendindex[i] = PreviousIndex+Previoussize;
};

MPI_Scatterv(matrix, sendrange, firstsendindex, MPI_DOUBLE, _matrix, sendrange[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD);

//Разослали

 nstrings = size;

  for (int i=0; i<ProcCount; i++)
{
int Previoussize = (i==0) ? 0 : range[i-1];
int PreviousIndex = (i==0) ? 0 : ui1[i-1];
int Portion = (i==0) ? 0 : range[i-1];
nstrings -= Portion;
range[i] = nstrings/(ProcCount-i);
ui1[i] = PreviousIndex+Previoussize;
};

//Рассылка вектора

   /* 
    -что рассылать
	-массив с количествами пересылаемых элеметов на каждый процесс
	-массив с номерами элеметов, с которых надо начинать рассылку из vector

	-куда принять
	-сколько элементов на каждый процесс
	*/

MPI_Scatterv(vector, range, ui1, MPI_DOUBLE, _vector, range[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD);
status = 1; 
MPI_Bcast(&status, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Bcast(&m, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
delete [] sendrange;
delete [] firstsendindex;
}

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

void StolbElimination(int IterationNumber, double *globmaxSystemstring)
{
	double delen;
    for (int i=0; i<str_count; i++)//для каждой строки в процессе
    {
     if (IndexVedIter[i] == -1)
      {
        delen = _matrix[i*size+IterationNumber] / globmaxSystemstring[IterationNumber];
        for (int j=IterationNumber; j<size; j++)
           {
			   _matrix[i*size + j] -= globmaxSystemstring[j]*delen;                                                  
		   };
           _vector[i] -= globmaxSystemstring[size]*delen;
                                 
	  };
	 };
}

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

void GaussElimination()
{ 
  int VedIndex;   // индекс ведущей строки на конкретном процессе
  struct { double MaxValue; int ProcRank; } Localmax, globmax; //максимальный элемент+номер процесса, у которого он
  double* pglobmaxstring = new double [size+1]; //т.е. строка матрицы+значение вектора
  for (int i=0; i<size; i++) //главный цикл решения
  {
   // Вычисление ведущей строки
   double MaxValue = 0;
   int tmp_index = -1;
   for (int j=0; j<str_count; j++)
   {
    tmp_index = j;
    if ((IndexVedIter[j] == -1)&&(MaxValue < fabs(_matrix[i+size*j])))
     {
      MaxValue = fabs(_matrix[i+size*j]);
      VedIndex = j;
     };
   };

Localmax.MaxValue = MaxValue;
Localmax.ProcRank = ProcRank;

//каждый процесс рассылает свой локально максимальный элемент по всем столцам, все процесы принимают уже глобально максимальный элемент
MPI_Allreduce(&Localmax, &globmax, 1, MPI_DOUBLE_INT, MPI_MAXLOC, MPI_COMM_WORLD);

//Вычисление ведущей строки всей системы
if ( ProcRank == globmax.ProcRank )
{
	if (globmax.MaxValue == 0)
	{
		status = 2;
		MPI_Barrier(MPI_COMM_WORLD);
		MPI_Send(&status, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD);
		IndexVedIter[tmp_index] = i;
		IndexVedStr[i] = ui1[ProcRank] + VedIndex;
		continue;

	} 
	else 
	{
		IndexVedIter[VedIndex] = i;  // Номер итерации, на которой строка с локальным номером является ведущей для всей системы
		IndexVedStr[i] = ui1[ProcRank] + VedIndex;   //Вычисленный номер ведущей строки системы
	};
 };
MPI_Bcast(&IndexVedStr[i], 1, MPI_INT, globmax.ProcRank, MPI_COMM_WORLD);
if (ProcRank == globmax.ProcRank)
{
	for (int j=0; j<size; j++)
		pglobmaxstring[j] = _matrix[VedIndex*size + j];
	pglobmaxstring[size] = _vector[VedIndex];
};
//Рассылка ведущей строки всем процессам
MPI_Bcast(pglobmaxstring, size+1, MPI_DOUBLE, globmax.ProcRank, MPI_COMM_WORLD);
//Исключение неизвестных в столбце с номером i
StolbElimination(i, pglobmaxstring);
  };
}

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

void Frp(int stringIndex, // номер строки, которая была ведущей на определеной итерации
		int &iterationprocrank, // процесс, на котором эта строка
		int &IterationItervedindex) // локальный номер этой строки (в рамках одного процесса)
{
	for (int i=0; i<ProcCount-1; i++) //Определяем ранг процесса, содержащего данную строку
    {
		if ((ui1[i]<=stringIndex)&&(stringIndex<ui1[i+1]))
			iterationprocrank = i;
	}
	if (stringIndex >= ui1[ProcCount-1])
		iterationprocrank = ProcCount-1;
	IterationItervedindex = stringIndex - ui1[iterationprocrank];

}

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

void GaussReverse()
{
	int IterProcRank;  // Ранг процесса, хранящего текущую ведущую строку
	int IndexVed;    // локальный на своем процессе номер текущей ведущей
	double IterResult;   // значение Xi, найденное на итерации
	double val;
	// Основной цикл
	for (int i=size-1; i>=0; i--)
    {
		Frp(IndexVedStr[i], IterProcRank, IndexVed);
		// Определили ранг процесса, содержащего текущую ведущую строку, и номер этой строки на процессе 
		// Вычисляем значение неизвестной
		if (ProcRank == IterProcRank)
        {
			if (_matrix[IndexVed*size+i] == 0)
			{
				if (_vector[IndexVed] == 0)
					IterResult = m;  
				else 
				{
					status = 0;
					MPI_Barrier(MPI_COMM_WORLD);
					MPI_Send(&status, 1, MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD);
					break;
				};
			} 
			else
				IterResult = _vector[IndexVed]/_matrix[IndexVed*size+i];
				_result[IndexVed] = IterResult; //нашли значение переменной
		};
		MPI_Bcast(&IterResult, 1, MPI_DOUBLE, IterProcRank, MPI_COMM_WORLD);
		for (int j=0; j<str_count; j++) //подстановка найденной переменной
			if (IndexVedIter[j] < i)
             {
				 val = _matrix[size*j + i] * IterResult;
				 _vector[j] -= val;
			};
	};
}

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

void Gauss()
{
	GaussElimination();
	GaussReverse();
	//сбор данных, передача от всех одному (нулевому процессу)
	MPI_Gatherv(_result, range[ProcRank], MPI_DOUBLE, result, range, ui1, MPI_DOUBLE, 0, MPI_COMM_WORLD);
} 

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

void main(int argc, char* argv[])
{
 //setvbuf(stdout, 0, _IONBF, 0);
 MPI_Init(&argc, &argv);
 MPI_Comm_rank (MPI_COMM_WORLD, &ProcRank);

 if (ProcRank == 0) setvbuf(stdout, 0, _IONBF, 0);

 MPI_Comm_size (MPI_COMM_WORLD, &ProcCount);
 MPI_Barrier(MPI_COMM_WORLD);
 ProcInitialization();
 Distribution();
 MPI_Barrier(MPI_COMM_WORLD);
 start = MPI_Wtime();
 Gauss();
 MPI_Barrier(MPI_COMM_WORLD);
 finish = MPI_Wtime();
 deltime = (finish-start);
 if (ProcRank == 0)
 {
	 if (status == 1) // решение найдено
	 {
		 printf("\nRoots: \n");
		 //for (int i = 0; i<size; i++)
			 //printf(" \nresult[%i] = %f ", i, result[IndexVedStr[i]]);
	 };
	 if (status == 0) printf("\nNo roots.\n"); // решений нет
	 if (status == 2) // решений бесконечно много
	 {
		 printf("\nContinum. Solution: \n\n");
		 //for (int i = 0; i<size; i++)
			 //printf("\nresult[%d] = %f ", i, result[IndexVedStr[i]]);
	 };
	 printf("\n\nTime= %f\n", deltime);
 };
 if (ProcRank == 0)
 {
	 printf("\nFinished!");
	 _getch();
 };
 MPI_Finalize();
 delete [] matrix;
 delete [] vector; 
 delete [] result;
}

Новости

22.10.2012
04.09.2012
05.04.2012
06.03.2012
02.03.2012