Реализация метода Гаусса. Решения СЛАУ в системе MPI, страница 3

MPI_Send(comp,size,MPI_INT,1,tag,ring);

};

};

if(rank){

MPI_Recv(&dim,1,MPI_INT,sour,tag,ring,&st);

MPI_Recv(comp,size,MPI_INT,sour,tag,ring,&st);

if(rank<(size-1)){

MPI_Send(&dim,1,MPI_INT,dest,tag,ring);

MPI_Send(comp,size,MPI_INT,dest,tag,ring);

};

};

for(i=0;i<=size-1,comp[i]>0;i++);

size=i<size?i:size;

if(!comp[rank])exit(0);

/* Memory allocation */

A=(float *)malloc(sizeof(float)*(dim+1)*comp[rank]);

res=(float *)malloc(sizeof(float)*dim);

B=(float *)malloc((dim+1)*sizeof(float));

if(!A||!res||!B){printf("Can't allocate memory...\n");return 1;};

if(!rank){/*Processor with rank=0 initialise*/

counter=0;

for(i=1;i<=dim;i++){/*For each row of the whole matrix...*/

if((i-1)%size==0)/*Own string*/{

for(j=1;j<=dim+1;j++)fscanf(inp,"%f",A+counter*(dim+1)+j-1);

counter++;

}else{

for(j=1;j<=dim+1;j++)fscanf(inp,"%f",B+j-1);

MPI_Send(B,dim+1,MPI_FLOAT,(i-1)%size,tag,ring);

};

};

if(fclose(inp))printf("Error closing file...\n");

time(tp1);

};

if(rank){

/*Now we'll recieve matrix*/

for(i=1;i<=comp[rank];i++){

MPI_Recv(A+(i-1)*(dim+1),dim+1,MPI_FLOAT,0,tag,ring,&st);

};

};

/*Matrix transforming*/

for(i=1;i<=comp[rank];i++){

for(j=1;j<(rank+1+size*(i-1));j++){

if(((j-1)%size)==rank){

if(A[(i-1)*(dim+1)+j-1]){

localnum=(j-1)/size+1;

c=-A[(i-1)*(dim+1)+j-1]/A[(localnum-1)*(dim+1)+j-1];

for(j1=j;j1<=dim+1;j1++)A[(i-1)*(dim+1)+j1-1]+=c*A[(localnum-1)*(dim+1)+j1-1];

};

}else if(j>(rank+1+size*(i-2))){

MPI_Recv(B,dim+1,MPI_FLOAT,(j-1)%size,tag,ring,&st);

for(k=i;k<=comp[rank];k++)if(A[(k-1)*(dim+1)+j-1]){

c=-A[(k-1)*(dim+1)+j-1]/B[j-1];

for(j1=j;j1<=dim+1;j1++)A[(k-1)*(dim+1)+j1-1]+=c*B[j1-1];

};

};

};

for(j=rank+1+size*(i-1)+1,compID=rank+1;(j<=dim)&&(compID<=rank+size-1);j++,compID++){

MPI_Send(A+(dim+1)*(i-1),dim+1,MPI_FLOAT,compID%size,sendtag,ring);

}

for(j=i+1;j<=comp[rank];j++)if(A[(j-1)*(dim+1)+rank+size*(i-1)]){

c=-A[(j-1)*(dim+1)+rank+size*(i-1)]/A[(i-1)*(dim+1)+rank+size*(i-1)];

for(j1=rank+size*(i-1)+1;j1<=dim+1;j1++)A[(j-1)*(dim+1)+j1-1]+=c*A[(i-1)*(dim+1)+j1-1];

};

};

/*Result calculating*/

for(i=comp[rank];i>=1;i--){

if((rank+1+(i-1)*size)==dim){

}else MPI_Recv(res,dim,MPI_FLOAT,dest,tag,ring,&st);

res[rank+1+(i-1)*size-1]=A[i*(dim+1)-1];

for(j=rank+1+(i-1)*size+1;j<=dim;j++)res[rank+1+(i-1)*size-1]-=res[j-1]*A[(i-1)*(dim+1)+j-1];

if(!A[(i-1)*(dim+1)+rank+(i-1)*size]){

printf("Matrix is null determined...\n");

MPI_Finalize();

exit(0);

};

res[rank+1+(i-1)*size-1]/=A[(i-1)*(dim+1)+rank+(i-1)*size];

if((rank+1+(i-1)*size)!=1){

MPI_Send(res,dim,MPI_FLOAT,sour,tag,ring);

};

};

if(!rank){

time(tp2);

time_=difftime(*tp2,*tp1);

printf("time=%f",time_);

if(!(outp=fopen("./output.txt","w"))){

printf("Couldn't open output file...\n");

exit(1);

};

fprintf(outp,"Result:\n");

for(i=1;i<=dim;i++)fprintf(outp,"%f ",res[i-1]);

fprintf(outp,"\nExecution time: %f\n",time_);

};

if(A)free(A);

if(B)free(B);

if(comp)free(comp);

if(res)free(res);

MPI_Finalize();

return 0;

};

III.  Результаты:

Для тестирования на больших матрицах была написана программа, генерирующая СЛАУ с единичной матрицей, единичным вектором правых частей и, очевидно, единичным решением.

Расчёт на однопроцессорном компьютере (10 виртуальных процессоров)

Программа 1:

Размерность матрицы

Время счёта

100

9

500

50

Программа 2:

Размерность матрицы

Время счёта

100

11

500

55

Программа 1:

Размерность матрицы

Время счёта

Программа 2:

Размерность матрицы

Время счёта

IV.  Выводы

Из результатов на однопроцессорной машине следует, что во втором методе больше времени, чем в первом  тратится на пересылку данных, а именно, время во втором методе больше примерно на 10%.

Очевидно, что на одном компьютере никакого выигрыша от второго метода быть не должно, его и нет, он работает дольше только за счёт большего числа пересылок данных между процессорами.