Добавил:
Tushkan
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
#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;
}