Скачиваний:
25
Добавлен:
28.06.2014
Размер:
5.29 Кб
Скачать
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	int procNum, procRank, i, j, k, nRows, nRowsOnProc;
	double **partMatr, **partMu;
	double *buf;
	int *map;
	FILE *LU, *L, *U;

	double t1, t2, dt, mu;

	MPI_Init(&argc, &argv);
	MPI_Comm_size(MPI_COMM_WORLD, &procNum);
	MPI_Comm_rank(MPI_COMM_WORLD, &procRank);
	MPI_Status Status;

	// Чтение размерности системы и рассылка ее исполнителям
	if (procRank == 0)
	{
		t1 = MPI_Wtime();
		if ((LU = fopen("lu.txt", "r")) == NULL)
			printf("Unable to open input file to read size of matrix\n");
		fscanf(LU, "%d\n", &nRows);
	}
	MPI_Bcast(&nRows, 1, MPI_INT, 0, MPI_COMM_WORLD);
	nRowsOnProc = 1 + nRows /procNum;

	// Выделение памяти для фрагментов матрицы, буфера, карты и коэффициентов матрицы L
	if ((partMatr = (double**)malloc(nRowsOnProc * sizeof(double*))) == NULL)
		printf("Memory allocation failed. Haven't enough memory for partMatr\n");
	if ((buf = (double*)malloc(nRows * sizeof(double))) == NULL)
		printf("Memory allocation failed. Haven't enough memory for buf\n");
	if ((map = (int*)malloc(nRows * sizeof(int))) == NULL)
		printf("Memory allocation failed. Haven't enough memory for map\n");
	if ((partMu = (double**)malloc(nRowsOnProc * sizeof(double*))) == NULL)
		printf("Memory allocation failed. Haven't enough memory for partMu\n");
	for (i = 0; i < nRowsOnProc; i++)
	{
		if ((partMatr[i] = (double*)malloc(nRows * sizeof(double))) == NULL)
			printf("Memory allocation failed. Haven't enough memory for partMatr[%d]\n", i);
		if ((partMu[i] = (double*)malloc((procRank + i * procNum) * sizeof(double))) == NULL)
			printf("Memory allocation failed. Haven't enough memory for partMu[%d]\n", i);
	}

	for (i = 0; i < nRows; i++)
		map[i] = i % procNum;

	// Чтение матрицы и распределение ее между исполнителями
	if (procRank == 0)
	{
		for (i = 0; i < nRows; i++)
		{
			if (map[i] == 0)
				for (j = 0; j < nRows; j++)
					fscanf(LU, "%lg", &partMatr[i / procNum][j]);
			else
			{
				for (j = 0; j < nRows; j++)
					fscanf(LU, "%lg", &buf[j]);
				MPI_Send(buf, nRows, MPI_DOUBLE, map[i], i / procNum, MPI_COMM_WORLD);
			}
			fscanf(LU, "\n");
		}
		fclose(LU);
	}

	// Прием исполнитемями своих фрагменов матрицы
	else
	{
		for (i = 0; procRank + i * procNum < nRows; i++)
			MPI_Recv(&partMatr[i][0], nRows, MPI_DOUBLE, 0, i, MPI_COMM_WORLD, &Status);
	}

	// Формирование фрагментов искомых матриц L и U на вычислителях
	for (k = 0; k < nRows - 1; k++)
	{
		if (map[k] == procRank)
			for (i = k; i < nRows; i++)
				buf[i] = partMatr[k / procNum][i];
		MPI_Bcast(buf + k, nRows - k, MPI_DOUBLE, map[k], MPI_COMM_WORLD);
		for (i = k + 1; i < nRows; i++)
		{
			if (map[i] == procRank)
			{
				mu = partMu[i / procNum][k] = partMatr[i / procNum][k] / buf[k];
				for (j = k; j < nRows; j++)
					partMatr[i / procNum][j] -= mu * buf[j];
			}
		}
	}

	// Получение результатов со всех исполнителей и запись их в файл
	if (procRank == 0)
	{
		// Открытие файлов для записи результатов
		if ((L = fopen("l.txt", "w")) == NULL)
			printf("Unable to open output file to write matrix L\n");
		if ((U = fopen("u.txt", "w")) == NULL)
			printf("Unable to open output file to write matrix U\n");
		fprintf(L, "%d %d\n", nRows, nRows);
		fprintf(U, "%d %d\n", nRows, nRows);

		// Выводим матрицу U
		for (i = 0; i < nRows; i++)
		{
			if (map[i] == 0)
			{
				for (j = 0; j < nRows; j++)
					if (j >= i)
						fprintf(U, "%f ", partMatr[i / procNum][j]);
					else
						fprintf(U, "0 ");
				fprintf(U, "\n");
				free(partMatr[i / procNum]);
			}
			else
			{
				MPI_Recv(buf + i, nRows - i, MPI_DOUBLE, map[i], i, MPI_COMM_WORLD, &Status);
				for (j = 0; j < nRows; j++)
					if (j >= i)
						fprintf(U, "%f ", buf[j]);
					else
						fprintf(U, "0 ");
				fprintf(U, "\n");
			}
		}

		// Выводим матрицу L
		for (i = 0; i < nRows; i++)
		{
			if (map[i] == 0)
			{
				for (j = 0; j < nRows; j++)
				{
					if (i > j)
						fprintf(L, "%f ", partMu[i / procNum][j]);
					else
					{
						if (i == j)
							fprintf(L, "1 ");
						else
							fprintf(L, "0 ");
					}
				}
				fprintf(L, "\n");
				free(partMu[i / procNum]);
			}
			else
			{
				MPI_Recv(buf, i, MPI_DOUBLE, map[i], i, MPI_COMM_WORLD, &Status);
				
				for (j = 0; j < nRows; j++)
				{
					if (i > j)
						fprintf(L, "%f ", buf[j]);
					else
					{
						if (i == j)
							fprintf(L, "1 ");
						else
							fprintf(L, "0 ");
					}
				}
				fprintf(L, "\n");
			}
		}
		// Закрытие файлов
		fclose(L);
		fclose(U);
	}
	else
	{
		// Шлем матрицу U
		for (i = 0; procRank + i * procNum < nRows; i++)
		{
			j = procRank + i * procNum;
			MPI_Send(&partMatr[i][j], nRows - j, MPI_DOUBLE, 0, j, MPI_COMM_WORLD);
			free(partMatr[i]);
		}

		// Шлем матрицу L
		for (i = 0; procRank + i * procNum < nRows; i++)
		{
			j = procRank + i * procNum;
			MPI_Send(&partMu[i][0], j, MPI_DOUBLE, 0, j, MPI_COMM_WORLD);
			free(partMu[i]);
		}
	}

	// Вывод характеристик решения
	if (procRank == 0)
	{
		t2 = MPI_Wtime();
		dt = t2 - t1;
		printf("LU-decomposition of matrix takes %f sec\n", dt);
		printf("Size of matrix is %d\nNumber of processes is %d\n", nRows, procNum);
	}

	// Освобождение памяти
	free(partMatr);
	free(partMu);
	free(buf);
	free(map);

	MPI_Finalize();
	return 0;
}
Соседние файлы в папке LU-разложение матрицы (Буренков).source