dims[0]=0; //for auto creation
MPI_Dims_create(size,ND,dims);
MPI_Cart_create(MPI_COMM_WORLD,ND,dims,per,reord,&ring); //создание топологии
MPI_Cart_shift(ring,0,-1,&prev,&next); //определение соседей
//Read data from file (last computer do it)
if (rank == (size-1))
{ //Read matrix dimension and sent it to others
fp=fopen("input.txt","rt");
fscanf(fp,"%d",&n);
tau=1.5/n;
for (i=0;i<size-1;i++)
MPI_Send(&n,1,MPI_INT,i,tag,ring);
L=n/size+1; //Calculate the width
/* Начальное количество элементов у вектора Y0 для каждого компьютера
Начальное значение указателя откуда нужно начинать умножение */
start=size-(L*size-n);
//Выделение памяти под матрицу A и вектор b
A=(double**)malloc(L*sizeof(double*));
for (i=0;i<L;i++)
A[i]=(double*)malloc((n+1)*sizeof(double));
//Считывание матрицы А и вектора b из файла
//для rank<start
for(i=0;i<start;i++)
{
for(j=0;j<L;j++)
for(k=0;k<n+1;k++)
fscanf(fp,"%lf",&A[j][k]);
if (i!=size-1)
{
for(j=0;j<L;j++)
MPI_Send(A[j],(n+1),MPI_DOUBLE,i,tag,ring);
}
}
//для rank>start
for(i=start;i<size;i++)
{
for (j=0;j<L-1;j++)
for(k=0;k<n+1;k++)
fscanf(fp,"%lf",&A[j][k]);
if (i!=size-1)
{
for(j=0;j<L-1;j++)
MPI_Send(A[j],(n+1),MPI_DOUBLE,i,tag,ring);
}
}
fclose(fp);
}
else
{
//Получить размерность от последнего
MPI_Recv(&n,1,MPI_INT,size-1,tag,ring,&st);
//Выделить память под А и В
L=n/size+1;
tau=1.5/n;
start=size-(L*size-n);
A=(double**)malloc(L*sizeof(double));
for (i=0;i<L;i++)
A[i]=(double*)malloc((n+1)*sizeof(double));
//Получение матрицы от последнего компьютера
if(rank<start)
{
for(j=0;j<L;j++)
MPI_Recv(A[j],(n+1),MPI_DOUBLE,size-1,tag,ring,&st);
}
else
{
for(j=0;j<L-1;j++)
MPI_Recv(A[j],(n+1),MPI_DOUBLE,size-1,tag,ring,&st);
}
if(rank==0)
starttime=time(NULL);
}
Y0=(double*)malloc((L+1)*sizeof(double));
Y1=(double*)malloc((L+1)*sizeof(double));
//Инициализация Y0 and Y1
for(i=0;i<L+1;i++)
{
Y0[i]=0;
Y1[i]=0;
}
//printf("L=%d\n",L);
Continue:
if (rank < start)
{
Y0[L]=L;
d=rank*L;
}
else
{
Y0[L]=L-1;
d=start*L+(rank-start)*(L-1);
}
iter=iter+1;
flag=0;
if (rank < start) dim=L;
else dim=L-1;
// Умножение матрицы на вектор
for(k=0;k<size;k++) // Цикл по компьтерам
{
if (rank < start) dim=L;
else dim=L-1;
for (j=0;j<dim;j++) // Цикл по строкам
for (m=0,i=d;i<d+Y0[L];i++,m++) // Цикл по столбцам
Y1[j]+=A[j][i]*Y0[m];
d=(d+(int)Y0[L])%n;
MPI_Sendrecv_replace(Y0,L+1,MPI_DOUBLE,next,tag,prev,tag,ring,&st);
}
// Вычисление решения на текущей итерации
if (rank < start) dim=L;
else dim=L-1;
for (j=0;j<dim;j++) // Цикл по строкaм
Y1[j]=Y0[j]-tau*(Y1[j]-A[j][n]);
// for(j=0;j<dim;j++)
// printf("Rank=%d Y1[%d]=%lf iter=%d\n",rank,j,Y1[j],iter);
//Проверка условия выхода
if (rank < start) dim=L;
else dim=L-1;
for (i=0;i<dim;i++)
if (fabs((Y1[i]-Y0[i])/Y1[i])>Eps) flag=1;
//Посылка нулевому компьютеру данных, чтобы он принял решение
//об окончании или продолжении счета.
// if (flag==1)
if (rank!=0)
{
MPI_Send(&flag,1,MPI_INT,0,tag,ring); //send data to comp. number zero
MPI_Recv(&flag,1,MPI_INT,0,tag,ring,&st); //receive decision
}
else
{
//Receive datas from all computers
for(i=1;i<size;i++)
{
MPI_Recv(&recv_flag,1,MPI_INT,i,tag,ring,&st);
if(recv_flag==1) flag=1;
}
//Send to all computers the decision
for(i=1;i<size;i++)
MPI_Send(&flag,1,MPI_INT,i,tag,ring);
}
if (flag==1)
{
if (rank < start) dim=L;
else dim=L-1;
for (i=0;i<dim;i++)
{
Y0[i]=Y1[i];
Y1[i]=0;
}
goto Continue;
}
else
goto Finish;
Finish:
//Вывод результата
if(rank==0)
{
finishtime=time(NULL);
Result=(double*)malloc((size*(L+1))*sizeof(double));
for(i=0;i<L+1;i++)
Result[i]=Y1[i];
for(i=1;i<size;i++)
{
if (i < start)
MPI_Recv(&Result[i*L],L,MPI_DOUBLE,i,tag,ring,&st);
else
MPI_Recv(&Result[start*L+(i-start)*(L-1)],L-1,MPI_DOUBLE,i,tag,ring,&st);
}
fp=fopen("output.txt","wt");
for(j=0;j<n;j++)
fprintf(fp,"%lf\n",Result[j]);
fprintf(fp,"\nВремя(в секундах)=%f",difftime(finishtime,starttime));
fprintf(fp,"\nЧисло итераций=%d",iter);
fclose(fp);
}
else
if (rank < start)
MPI_Send(Y1,L,MPI_DOUBLE,0,tag,ring);
else
MPI_Send(Y1,L-1,MPI_DOUBLE,0,tag,ring);
for(i=0;i<L;i++)
free(A[i]);
free(A);
free(Y0);
free(Y1);
MPI_Finalize();
return 0;
}
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.