Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.

Предоплата всего

Подписываем
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Предоплата всего
Подписываем
МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ
ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ
Государственное образовательное учреждение
высшего профессионального образования
“Московский государственный технический университет
имени Н.Э. Баумана”
(МГТУ им. Н.Э.Баумана)
Факультет «Робототехника и комплексная автоматизация» (РК)
Кафедра «Системы автоматизированного проектирования» (РК-6)
Отчет по лабораторной работе №4
по курсу
«Разработка программных систем»
Выполнила: Митина Е.В.
группа РК6-112
Проверил: Федорук В.Г.
Подпись_________________
Дата___________________
Москва 2011
Вариант №3
Разработать средствами MPI параллельную программу решения двумерной нестационарной краевой задачи методом конечных разностей с использованием явной вычислительной схемы. Объект моделирования - прямоугольная пластина постоянной толщины. Подробности постановки подобной задачи даны ниже. Возможны граничные условия первого и второго рода в различных узлах расчетной сетки. Временной интервал моделирования и количество узлов расчетной сетки - параметры программы. Программа должна демонстрировать ускорение по сравнению с последовательным вариантом.
Примечание. Использование неявной вычислительной схемы связано с решением системы ЛАУ на каждом временном слое. Следовательно, распараллеливание решения краевой задачи неявным методом сводится к распараллеливанию решения системы ЛАУ методом Гаусса. Распараллеливание же метода Гаусса проще всего реализуется в ситуации, когда матрица коэффициентов системы имеет блочно-диагональный с окаймлением вид. Матрица же коэффициентов автоматически получит такой вид, если нумерацию узлов расчетной сетки вести по такой простой схеме: сначала "внутренние" узлы всех фрагментов, на которые разбивается стержень, а в последнюю очередь - "соединительные" узлы. Кстати, сказанное выше справедливо и для метода прогонки (поскольку этот метод - частный случай метода Гаусса). См. также замечание.
Текст программы
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <fstream>
#include <errno.h>
#include <cmath>
#include <mpi.h>
//#define _REENTRANT
#define RES_STDOUT
using namespace std;
//=================================================================
FILE *f, *r;
float dx = 1.0;
float dy = 1.0;
float dt = 0.1;
float tcur = 0.0;
float tmax = 20.0;
float length = 99.0;
float height = 399.0;
float a = 1.0;
float ms = 1.0;
float Tu = 0.0;
float Tl = -50.0;
float Tr = 100.0;
float Td = 0.0;
float Tf = 0.0;
const float Zero = 0.00001;
int p=0;
//=================================================================
unsigned GetTickCount (void) {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000 + tv.tv_usec/1000;
}
//=================================================================
int main (int argc, char *argv[]) {
// f=fopen("rez.txt","w+");
// r=fopen("graf.txt","w+");
int total = 0;
int myrank = 0;
MPI_Init (&argc, &argv);
MPI_Comm_size (MPI_COMM_WORLD, &total);
MPI_Comm_rank (MPI_COMM_WORLD, &myrank);
cout << "Total=" << total << ", rank=" << myrank << endl;
length *= ms;
height *= ms;
int xsz = (int)(length / dx);
int ysz = (int)(height / dy);
int area = xsz * ysz;
float *tempr;
float *tempr_other;
float *along_X_buf;
float *personal_X_buf;
float *X_other, *Y_other;
float *final_temp;
int xvar;
int yvar;
float Tvar;
unsigned starttime;
unsigned endtime;
int *position;
int startline;
int startcol;
/**************************************************/
int linesperthread = (ysz-1)/total;
/**************************************************/
try {
tempr = new float [area];
tempr_other = new float [area];
along_X_buf = new float [xsz*total*2];
personal_X_buf = new float [xsz*2];
X_other = new float [xsz];
Y_other = new float [ysz];
position = new int [2*total];
final_temp = new float [xsz * linesperthread + xsz];
}
catch(bad_alloc xa) {
cerr << strerror(errno) << endl;
exit(1);
}
/**************************************************/
for(int i = 0; i < ysz; i++) {
for(int j = 0; j < xsz; j++) {
tempr[i * xsz + j] = Tf;
}
}
for(int i = 0; i < xsz; i++) {
tempr[i] = Tu;
}
for(int i = 0; i < xsz; i++) {
tempr[(ysz-1) * xsz + i] = Td;
}
for(int i = 0; i < ysz; i++) {
tempr[i * xsz] = Tl;
}
for(int i = 0; i < ysz; i++) {
tempr[i * xsz + (xsz-1)] = Tr;
}
xvar = 0;
yvar = 0;
Tvar = -50.0;
tempr[yvar*xsz + xvar] = Tvar;
/**************************************************/
if (!myrank) {
starttime = 0;
endtime = 0;
starttime = GetTickCount();
startline = 1;
startcol = 0;
for(int line = 0; line < ysz-1; line += linesperthread) {
position[line/linesperthread * 2] = line + 1;
position[line/linesperthread * 2 + 1] = 0;
}
}
MPI_Bcast((void *)position, 2*total, MPI_INT, 0, MPI_COMM_WORLD);
startline = position[2*myrank];
startcol = position[2*myrank + 1];
/**************************************************/
//tcur = tmax-dt;
while(tcur < tmax) {
tcur += dt;
if (!myrank) {
#ifdef RES_STDOUT
cout << "Time step " << tcur << "/" << tmax << endl;
#endif
#ifndef RES_STDOUT
cout.setf(ios::showpoint);
cout << "\rTime step " << tcur << "/" << tmax;
cout.unsetf(ios::showpoint);
#endif
}
if (!myrank) {
tempr[yvar*xsz + xvar] = Tvar;
#ifdef RES_STDOUT
// cout << "==========================" << endl;
//for(int q = 0; q < ysz; q++) {
// for(int w = 0; w < xsz; w++) {
// printf("%#8.2f ", tempr[q * xsz + w]);
// fprintf(f,"%d %d %#8.2f \n",w, q, tempr[q * xsz + w]);
// }
// cout << endl;
// }
// fprintf(f,"\n");
// p++;
#endif
}
for(int i = startline; i < (linesperthread + startline); i++) {
if(i >= ysz)
break;
for(int k = 1; k < (xsz-1); k++) {
X_other[k] = tempr[i*xsz + (k+1)]*a*dt/(dx*dx) +
tempr[i*xsz + (k-1)]*a*dt/(dx*dx) +
tempr[i*xsz + k]*(1/dt - 2*a/(dx*dx))*dt;
}
X_other[0] = tempr[i*xsz];
X_other[xsz-1] = tempr[i*xsz + (xsz-1)];
for(int n = 0; n < xsz; n++) {
tempr[i * xsz + n] = X_other[n];
}
}
/*if (!myrank) {
#ifdef RES_STDOUT
cout << "==========================" << endl;
for(int q = 0; q < ysz; q++) {
for(int w = 0; w < xsz; w++) {
printf("%#8.2f ", tempr[q * xsz + w]);
}
cout << endl;
}
#endif
tempr[yvar*xsz + xvar] = Tvar;
}*/
if(!myrank) {
for(int ri = 1; ri < total; ri++) {
for(int b = 0; b < xsz; b++) {
along_X_buf[ri * xsz * 2 + b] = tempr[position[2*ri] * xsz - xsz + b];
}
}
for(int ri = 0; ri < total-1; ri++) {
for(int b = 0; b < xsz; b++) {
along_X_buf[ri * xsz * 2 + b + xsz] = tempr[position[2*(ri+1)] * xsz + b];
}
}
}
MPI_Scatter((void *)along_X_buf, 2*xsz, MPI_FLOAT, (void *)personal_X_buf, 2*xsz, MPI_FLOAT, 0, MPI_COMM_WORLD);
if(myrank > 0) {
for(int b = 0; b < xsz; b++) {
tempr[startline * xsz + b - xsz] = personal_X_buf[b];
}
}
if(myrank < (total - 1)) {
for(int b = 0; b < xsz; b++) {
tempr[(startline + linesperthread) * xsz + b] = personal_X_buf[b + xsz];
}
}
for(int i = 1; i < (xsz-1); i++) {
for(int k = startline; k < (linesperthread + startline); k++) {
Y_other[k] = tempr[(k+1)*xsz + i]*a*dt/(dy*dy) +
tempr[(k-1)*xsz + i]*a*dt/(dy*dy) +
tempr[k*xsz + i]*(1/dt - 2*a/(dy*dy))*dt;
}
Y_other[0] = 0; //tempr[i];
Y_other[ysz-1] = 0; //2*tempr[(ysz-2)*xsz + i]*a*dt/(dy*dy) +
// tempr[(ysz-1)*xsz + i]*(1/dt - 2*a/(dy*dy))*dt;
for(int n = 0; n < ysz; n++) {
tempr[n * xsz + i] = Y_other[n];
}
}
if(myrank > 0) {
for(int b = 0; b < xsz; b++) {
personal_X_buf[b] = tempr[startline * xsz + b];
}
}
if(myrank < (total - 1)) {
for(int b = 0; b < xsz; b++) {
personal_X_buf[b + xsz] = tempr[(startline + linesperthread) * xsz - xsz + b];
}
}
MPI_Gather((void *)personal_X_buf, 2*xsz, MPI_FLOAT, (void *)along_X_buf, 2*xsz, MPI_FLOAT, 0, MPI_COMM_WORLD);
if(!myrank) {
for(int ri = 1; ri < total; ri++) {
for(int b = 0; b < xsz; b++) {
tempr[position[2*ri] * xsz + b] = along_X_buf[ri * xsz * 2 + b];
}
}
for(int ri = 0; ri < total-1; ri++) {
for(int b = 0; b < xsz; b++) {
tempr[position[2*(ri+1)] * xsz - xsz + b] = along_X_buf[ri * xsz * 2 + b + xsz];
}
}
}
}
if(myrank != (total - 1)) {
for(int l = startline; l < (startline + linesperthread); l++) {
for(int i = 1; i < (xsz - 1); i++) {
final_temp[(l-startline)*xsz + i] = tempr[l*xsz + i];
}
}
}
else {
for(int l = startline; l < ysz; l++) {
for(int i = 1; i < (xsz - 1); i++) {
final_temp[(l-startline)*xsz + i] = tempr[l*xsz + i];
}
}
}
MPI_Gather((void *)final_temp, linesperthread*xsz, MPI_FLOAT, (void *)tempr_other, linesperthread*xsz, MPI_FLOAT, 0, MPI_COMM_WORLD);
for(int l = 1; l < ysz; l++) {
for(int i = 1; i < (xsz - 1); i++) {
tempr[l*xsz + i] = tempr_other[(l-1)*xsz + i];
}
}
/*
if(!myrank)
{
for(int yv =0 ; yv < ysz; yv++) {
for(int xv = 0; xv < xsz; xv++) {
fprintf(f,"%d %d %#8.2f \n", xv, yv, tempr[yv*ysz + xv]);
}
}
fprintf(f,"\n");*/
// }
if (!myrank) {
#ifdef RES_STDOUT
// f=fopen("rez.txt","w");
// if(!f) { perror("ne otkrilsya"); exit(0);}
// cout << "==========================" << endl;
//
//fclose(f);
// for (int k=1; k<p; k++)
// {fprintf(r,"splot 'rez.txt' every :::%d::%d\npause 0.1\n", k, k);}
//fclose(r);
#endif
}
endtime = GetTickCount();
cout << "Vremya ms: " << (endtime - starttime) << endl;
if (!myrank) {
endtime = GetTickCount();
cout << "\n-----------------------------------" << endl;
cout << "Vremya ms: " << (endtime - starttime) << endl;
}
delete [] tempr;
delete [] along_X_buf;
delete [] personal_X_buf;
delete [] X_other;
delete [] Y_other;
delete [] position;
delete [] final_temp;
delete [] tempr_other;
MPI_Finalize();
exit(EXIT_SUCCESS);
}
Результат работы программы
Корректность работы программы проверялась на прямоугольной пластинке шириной 10 и длиной 20.
Программа показала ускорение при решении задачи для 30000 узлов ( ширина 100, длина 300):
mpiexec -nolocal -perhost 1 -np 1 lab4 425мс
mpiexec -nolocal -perhost 1 -np 2 lab4 266мс
mpiexec -nolocal -perhost 1 -np 4 lab4 213мс
mpiexec -nolocal -perhost 1 -np 8 lab4 218мс