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

Программа

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

float* pMatrix;  		// Матрица линейной системы
float* pVector;  		// Вектор правых частей линейной системы
int* pProcNum;			// Номера строк, обрабатываемых данным процессом
float* pProcRows; 		// Строки матрицы A
float* pProcVector; 	// Блок вектора b
int size;       		// Размер матрицы и векторов
int RowNum;     		// Количество строк матрицы 
double start, finish, duration;
int ProcNum;
int ProcRank;

void ProcessInitialization()
{
	if (ProcRank == 0) 	
	{
		int show = 0, fill;
		printf("\nEnter size of matrix: ");
		scanf("%i", &size);
		printf("Do you want to fill matrix manually(0) or automatically(1)?: ");
		scanf("%i", &fill);		
		if(fill)
		{
			printf("Do you want to see matrix(1) or not(0)?: ");
			scanf("%i", &show);
		}

		pMatrix = new float[size*size];
		pVector = new float[size];

		//автоматическое заполнение матрицы
		if(fill==1)
		{
			//int d = 1000;
			srand(1);
			for(int i=0; i  <  size*size; i++)
				pMatrix[i]=(float)(rand() % 1000);
			for(int i=0; i  <  size; i++)
				pVector[i]=(float)(rand() % 1000);
			if(show)
			{
				for(int i=0; i < size*size; i++)				 
					printf("\npMatrix[%i]=%f", i, pMatrix[i]);
				printf("\n");
				for(int i=0; i < size; i++)				
					printf("\npVector[%i]=%f", i, pVector[i]);
				printf("\n");
			}
		}
		//ручное заполнение матрицы
		else
		{
			printf("\nEnter values of pMatrix:\n");
			for(int i=0; i < size*size; i++)
			{
				printf("pMatrix[%i] = ", i);
				scanf("%f",&pMatrix[i]);
			}
			printf("\nEnter values of pVector:\n");
			for(int i=0; i < size; i++)
			{
				printf("pVector[%i] = ", i);
				scanf("%f",&pVector[i]);
			}
		}
	}

	//рассылка размера матрицы pMatrix на все процессы 0-м процессом
	MPI_Bcast(&size,1,MPI_INT,0,MPI_COMM_WORLD);	
	
	int StringNum;
	RowNum = 0;
	
	//определение числа строк, обрабатываемых данным процессом
	for(int j=0;j  <  =size/ProcNum;j++)
	{
		StringNum = ProcRank + j*ProcNum;
		if(StringNum  >  =size)
			break;
		RowNum++;		
	}
	pProcRows = new float[RowNum*size];
	pProcVector = new float[RowNum];
	pProcNum = new int[RowNum];	
}

void DataDistribution()
{
	//заполнение массива номеров строк pProcNum
	int StringNum;
	MPI_Status status;
	for(int j=0;j < RowNum;j++)
		pProcNum[j]=ProcRank + j*ProcNum;	
	
	//рассылка 0-м процессом остальным процессам значений матрицы pMatrix
	if(ProcRank==0)
	{
		int rank;
		for(int i=0;i < size*size;i++)
		{
			StringNum = i / size;
			rank = StringNum % ProcNum;
			if(rank!=0)
				MPI_Send(&pMatrix[i],1,MPI_FLOAT,rank,0,MPI_COMM_WORLD);
		}		
		for(int j=0;j < RowNum;j++)
			for(int k=0;k < size;k++)
				pProcRows[j*size+k]=pMatrix[pProcNum[j]*size+k];
	}
	else
		for(int i=0;i < RowNum*size;i++)
			MPI_Recv(&pProcRows[i],1,MPI_FLOAT,0,0,MPI_COMM_WORLD,&status);
	
	//рассылка 0-м процессом остальным процессам значений вектора pVector
	if(ProcRank==0)
	{
		int rank;
		for(int i=0;i < size;i++)
		{
			rank = i % ProcNum;
			if(rank!=0)
				MPI_Send(&pVector[i],1,MPI_FLOAT,rank,1,MPI_COMM_WORLD);
		}
		for(int j=0;j < RowNum;j++)
			pProcVector[j]=pVector[pProcNum[j]];
	}
	else
		for(int i=0;i < RowNum;i++)
			MPI_Recv(&pProcVector[i],1,MPI_FLOAT,0,1,MPI_COMM_WORLD,&status);
}

void GaussForward() 
{	
	float maxProc;
	int StringNumMaxProc;
	float max;
	int StringNumMax;	//номер строки матрицы pMatrix, содержащей максимальный элемент на данном процессе
	float* swap;
	float swap_vect;
	int Proc_StringNumMax;
	int Proc_i;
	int rank;
	float coef;
	MPI_Status status;
	for(int i=0;i < size-1;i++)
	{
		//определение максимального элемента в столбце i (ниже главной диагонали) в строках данного процесса
		StringNumMax = size-1;		
		if(ProcRank == 0)
			max = fabs(pMatrix[i+(size-1)*size]);
		MPI_Bcast(&max,1,MPI_FLOAT,0,MPI_COMM_WORLD);
		for(int j=RowNum-1;j > =0;j--)
		{
			if(pProcNum[j] < i)
				break;
			if(max < fabs(pProcRows[i+j*size]))
			{
				max = fabs(pProcRows[i+j*size]);
				StringNumMax = pProcNum[j];
			}
		}
		//отправка максимального значения и номера строки 0-му процессу
		if(ProcRank != 0)
		{
			MPI_Send(&max,1,MPI_FLOAT,0,2,MPI_COMM_WORLD);
			MPI_Send(&StringNumMax,1,MPI_INT,0,3,MPI_COMM_WORLD);
		}
		//получение максимального значения и номера строки 0-ым процессом
		if(ProcRank == 0)
		{			
			for(int rank=1;rank < ProcNum;rank++)
			{
				MPI_Recv(&maxProc,1,MPI_FLOAT,rank,2,MPI_COMM_WORLD,&status);
				MPI_Recv(&StringNumMaxProc,1,MPI_INT,rank,3,MPI_COMM_WORLD,&status);
				if(max < maxProc)
					{
						max = maxProc;
						StringNumMax = StringNumMaxProc;
					}
			}			
		}
		MPI_Bcast(&StringNumMax,1,MPI_INT,0,MPI_COMM_WORLD);
		
		//определение номеров процессов, которым принадлежат строки, которые необходимо поменять местами
		Proc_StringNumMax = StringNumMax % ProcNum;
		Proc_i = i % ProcNum;
		if((StringNumMax != i) && (ProcRank == Proc_StringNumMax || ProcRank == Proc_i))
		{	
			//меняем местами строки StringNumMax и i
			if(Proc_StringNumMax == Proc_i)
			{
				swap = new float[size];
				int k_i = -1;
				int k_StringNumMax = -1;
				for(int j=0;j < RowNum;j++)
				{
					if(pProcNum[j] == i)
						k_i = j;
					if(pProcNum[j] == StringNumMax)
						k_StringNumMax = j;
				}
				for(int j=0;j < size;j++)
				{
					swap[j] = pProcRows[j+k_i*size];
					pProcRows[j+k_i*size] = pProcRows[j+k_StringNumMax*size];
					pProcRows[j+k_StringNumMax*size] = swap[j];					
				}
				swap_vect = pProcVector[k_i];
				pProcVector[k_i] = pProcVector[k_StringNumMax];
				pProcVector[k_StringNumMax] = swap_vect;
			}
			else
			{
				if(ProcRank == Proc_StringNumMax)
				{
					//передача своей строки процессу Proc_i
					int k = -1;
					for(int j=0;j < RowNum;j++)
						if(pProcNum[j] == StringNumMax)
						{
							k = j;
							break;
						}
					for(int j=0;j < size;j++)
							MPI_Send(&pProcRows[j+k*size],1,MPI_FLOAT,Proc_i,4,MPI_COMM_WORLD);
					MPI_Send(&pProcVector[k],1,MPI_FLOAT,Proc_i,7,MPI_COMM_WORLD);
				}
				if(ProcRank == Proc_i)
				{
					//запись строки процесса Proc_StringNumMax в массив swap
					swap = new float[size];
					for(int j=0;j < size;j++)
						MPI_Recv(&swap[j],1,MPI_FLOAT,Proc_StringNumMax,4,MPI_COMM_WORLD,&status);
					MPI_Recv(&swap_vect,1,MPI_FLOAT,Proc_StringNumMax,7,MPI_COMM_WORLD,&status);
					//передача своей строки процессу Proc_StringNumMax
					int k = -1;
					for(int j=0;j < RowNum;j++)
						if(pProcNum[j] == i)
						{
							k = j;
							break;
						}
					for(int j=0;j < size;j++)
						MPI_Send(&pProcRows[j+k*size],1,MPI_FLOAT,Proc_StringNumMax,5,MPI_COMM_WORLD);
					MPI_Send(&pProcVector[k],1,MPI_FLOAT,Proc_StringNumMax,8,MPI_COMM_WORLD);
				}
				if(ProcRank == Proc_StringNumMax)
				{
					//запись строки процесса Proc_i
					int k = -1;
					for(int j=0;j < RowNum;j++)
						if(pProcNum[j] == StringNumMax)
						{
							k = j;
							break;
						}
					for(int j=0;j < size;j++)
						MPI_Recv(&pProcRows[j+k*size],1,MPI_FLOAT,Proc_i,5,MPI_COMM_WORLD,&status);
					MPI_Recv(&pProcVector[k],1,MPI_FLOAT,Proc_i,8,MPI_COMM_WORLD,&status);
				}
				if(ProcRank == Proc_i)
				{
					int k = -1;
					for(int j=0;j < RowNum;j++)
						if(pProcNum[j] == i)
						{
							k = j;
							break;
						}
					for(int j=0;j < size;j++)
						pProcRows[j+k*size] = swap[j];
					pProcVector[k] = swap_vect;
				}
			}
		}	
		//
		//MPI_Barrier(MPI_COMM_WORLD);
		//рассылка строки i всем процессам, которым принадлежат строки c номером, большим i
		if(ProcRank == Proc_i)
		{
			int k = -1;
			for(int j=0;j < RowNum;j++)
				if(pProcNum[j] == i)
				{
					k = j;
					break;
				}
			for(int string=i+1;string < size;string++)
			{	
				rank = string % ProcNum;
				if(rank != Proc_i)
				{
					for(int j=0;j < size;j++)
						MPI_Send(&pProcRows[j+k*size],1,MPI_FLOAT,rank,6,MPI_COMM_WORLD);
					MPI_Send(&pProcVector[k],1,MPI_FLOAT,rank,9,MPI_COMM_WORLD);
				}
				else
					for(int j=0;j < RowNum;j++)
						if(pProcNum[j] == string)
							if(pProcRows[i+j*size] != 0)
							{
								coef = pProcRows[i+j*size]/pProcRows[i+k*size];
								pProcRows[i+j*size] = 0;
								pProcVector[j] = pProcVector[j] - coef*pProcVector[k];
								for(int m=i+1;m < size;m++)
									pProcRows[m+j*size] = pProcRows[m+j*size] - coef*pProcRows[m+k*size];						
							}
			}
		}
		if(ProcRank != Proc_i)
		{
			for(int j=0;j < RowNum;j++)
				if(pProcNum[j]  >  i)
				{
					swap = new float[size];
					for(int k=0;k < size;k++)
						MPI_Recv(&swap[k],1,MPI_FLOAT,Proc_i,6,MPI_COMM_WORLD,&status);
					MPI_Recv(&swap_vect,1,MPI_FLOAT,Proc_i,9,MPI_COMM_WORLD,&status);
					if(pProcRows[i+j*size] != 0)
					{
						coef = pProcRows[i+j*size]/swap[i];
						pProcRows[i+j*size] = 0;
						pProcVector[j] = pProcVector[j] - coef*swap_vect;
						for(int k=i+1;k < size;k++)
							pProcRows[k+j*size] = pProcRows[k+j*size] - coef*swap[k];
					}
				}
		}		
	}	
}

void GaussBack()
{
	int Proc_i;
	int rank;
	float res;
	MPI_Status status;
	for(int i=size-1;i > 0;i--)
	{
		Proc_i = i % ProcNum;
		if(ProcRank == Proc_i)
		{
			int k;
			for(int j=0;j < RowNum;j++)
				if(pProcNum[j] == i)
				{
					k = j;
					break;
				}
			pProcVector[k] = pProcVector[k]/pProcRows[i+k*size];
			pProcRows[i+k*size] = 1;
			for(int j=i-1;j > =0;j--)
			{
				rank = j % ProcNum;
				if(rank != Proc_i)
					MPI_Send(&pProcVector[k],1,MPI_FLOAT,rank,10,MPI_COMM_WORLD);
				else
				{
					int k_j;
					for(int m=0;m < RowNum;m++)
						if(pProcNum[m] == j)
						{
							k_j = m;
							break;
						}
					pProcVector[k_j] = pProcVector[k_j] - pProcRows[i+k_j*size]*pProcVector[k];
					pProcRows[i+k_j*size] = 0;
				}
			}			 
		}
		else
		{
			for(int j=RowNum-1;j > =0;j--)
				if(pProcNum[j] < i)
				{
					MPI_Recv(&res,1,MPI_FLOAT,Proc_i,10,MPI_COMM_WORLD,&status);
					pProcVector[j] = pProcVector[j] - pProcRows[i+j*size]*res;
					pProcRows[i+j*size] = 0;
				}			
		}		
		//MPI_Barrier(MPI_COMM_WORLD);		
	}
	if(ProcRank == 0)
	{
		pProcVector[0] = pProcVector[0]/pProcRows[0];
		pProcRows[0] = 1;
	}	
}

void Result()
{
	int rank;
	int k;
	for(int j=0;j < size;j++)
	{
		rank = j % ProcNum;
		if(ProcRank == rank)
			{				
				for(int m=0;m < RowNum;m++)
					if(pProcNum[m] == j)
					{
						k = m;
						break;
					}
				printf("\nResult[%i] = %f",j,pProcVector[k]);
			}
		MPI_Barrier(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);
	MPI_Comm_size (MPI_COMM_WORLD, &ProcNum);

	if (ProcRank == 0)
		printf("Gauss method is starting!");

	ProcessInitialization();
	DataDistribution();
	MPI_Barrier(MPI_COMM_WORLD);
	start = MPI_Wtime();
	GaussForward();
	GaussBack();
	//MPI_Barrier(MPI_COMM_WORLD);
	finish = MPI_Wtime();
	duration = finish - start;
	Result();
	if (ProcRank == 0)
	{
		printf("\n\nGauss method has finished!");
		printf("\n\nTime: %f",duration);
		getchar();
		getchar();
	}

	MPI_Finalize();
}

Новости

22.10.2012
04.09.2012
05.04.2012
06.03.2012
02.03.2012