У меня есть работающий код, но нужно немного переделать А именно,
матрицу необходимо читать с диска и только в процессе 0-го ранга(ну это я сама справлюсь). Данные для перемножения должны рассылаться из 0-го процесса во все остальные исходя из потребностей процесса. Необходимо предусмотреть, что количество MPI процессов будет ощутимо меньше числа строк/столбцов, следовательно (индекс столбца+1) нельзя использовать для адресации процесса для вычислений.
Вот, и как это предусмотреть?я что-то не понимаю.Люди-добрые, помогите пож-та исправить ЭТО:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MPI;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
using (new MPI.Environment(ref args))
{
Intracommunicator comm = Communicator.world;
int rank = comm.Rank;
int size = comm.Size;
double[,] A = { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } };
double[,] B = { { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 } };
int razmer = A.GetLength(0);
double[,] C = new double[razmer, razmer];
double[] tempMatrix = new double [size];
if (rank == 0)
{
Console.WriteLine("Matrica A");
vyvodvconsol(A);
Console.WriteLine("Matrica B");
vyvodvconsol(B);
}
if (rank == 0)
{
int IndexRank = 1;
for (int i = 0; i < razmer; i++)
{
for (int j = 0; j < razmer; j++)
{
int[] koordinata = new int[2] { i, j };
comm.Send(koordinata, IndexRank, 0);
IndexRank++;
}
}
comm.Gather(-1, 0, ref tempMatrix);
comm.Barrier();
C = PoluchMatricuIzPosledovat(tempMatrix, razmer);
Console.WriteLine("Matr C");
vyvodvconsol(C);
}
else
{
int[] koordinata = new int[2];
comm.Receive(0, 0, ref koordinata);
double resultat = Element(PoluchitStroku(koordinata[0], A), PoluchitStolbec(koordinata[1], B));
comm.Gather(resultat, 0, ref tempMatrix);
comm.Barrier();
}
}
}
public static void vyvodvconsol(double[,] matrix)
{
Console.WriteLine();
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
Console.Write(matrix[i, j]);
Console.Write(" ");
}
Console.Write('\n');
}
Console.WriteLine();
}
public static double[] PoluchitStroku(int idLine, double[,] M)
{
double[] result = new double[M.GetLength(1)];
for (int i = 0; i < result.Length; i++)
{
result[i] = M[idLine, i];
}
return result;
}
public static double[] PoluchitStolbec(int idColumn, double[,] M)
{
double[] result = new double[M.GetLength(0)];
for (int i = 0; i < result.Length; i++)
{
result[i] = M[i,idColumn];
}
return result;
}
public static double Element(double[] line, double[] column)
{
double result = 0;
for (int i = 0; i < line.Length; i++)
{
result += line[i] * column[i];
}
return result;
}
public static double[,] PoluchMatricuIzPosledovat(double[] matrix, int size)
{
double[,] resmatrix = new double[size, size];
int matrixIndex = 1;
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
resmatrix[i, j] = matrix[matrixIndex];
matrixIndex++;
}
}
return resmatrix;
}
}
}
ИЛИ код на С++:
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "mpi.h"
int new_rand(){
return rand()%10;
}
void SAR(int *array, int size){
int end,i;
end=array[size-1];
for(i=size-2;i>=0;i--)
array[i+1]=array[i];
array[0]=end;
}
void shift(int *array, int size, int count){
int i;
for(i=0;i<count;i++)
SAR(array,size);
}
/*Matrix output*/
void Out(int *M[], int size, FILE *F){
int i,j;
for (i=0;i<size;i++){
for(j=0;j<size;j++)
fprintf(F,"%i\t",M[i][j]);
fprintf(F,"\n");
}
};
int main (int argc, char* argv[]){
int N,i,j,k,p;
int **A, **B, **C, **A1, **C1, **B1, numproc, myid, m, portion, *ST;
double start, finish;
FILE *Fa,*Fb;
MPI_Request request;
MPI_Status status;
MPI_Init(&argc,&argv);
start=MPI_Wtime();
MPI_Comm_size(MPI_COMM_WORLD,&numproc);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
//----------------------------------------------------
if(myid==0){ //
if ((argc!=2)&&(argc!=4)&&(argc!=5)) //
{ //
printf("Wrong parameters.\n"); //
MPI_Abort(MPI_COMM_WORLD,-1); //
return 0; //
} //
N=atoi(argv[1]); //
if(N%numproc){ //
printf("Unsuficient size.\n"); //
MPI_Abort(MPI_COMM_WORLD,-1); //
} //
} //
//----------------------------------------------------
MPI_Bcast(&N, 1, MPI_INT, 0, MPI_COMM_WORLD);
ST=(int*)malloc(N*sizeof(int));
for(i=0;i<N;i++)
ST[i]=i;
portion=N/numproc;
//----------------------------------------------------
if(myid==0){ //
B=malloc(N*sizeof(int*)); //
A=malloc(N*sizeof(int*)); //
C=malloc(N*sizeof(int*)); //
for (i=0;i<N;i++){ //
A[i]=malloc(N*sizeof(int)); //
B[i]=malloc(N*sizeof(int)); //
C[i]=malloc(N*sizeof(int)); //
if ((!A[i])||(!C[i])){ //
fprintf(stderr,"Process %i : Out of memory.\n",myid);
MPI_Abort(MPI_COMM_WORLD,-1); //
return 0; //
} //
} //
} //
//----------------------------------------------------
B1=malloc(portion*sizeof(int*));
A1=malloc(portion*sizeof(int*));
C1=malloc(portion*sizeof(int*));
for(i=0;i<portion;i++){
A1[i]=malloc(N*sizeof(int));
B1[i]=malloc(N*sizeof(int));
C1[i]=malloc(N*sizeof(int));
if ((!C1[i])||(!A1[i])||(!B1[i])){
fprintf(stderr,"Process %i : Out of memory.\n",myid);
MPI_Abort(MPI_COMM_WORLD,-1);
}
}
//printf("Step1\n");///////////////////////////////////////////////
//====================================================
if(myid==0){ //
if (argc>=4){ //
Fa=fopen(argv[2],"r"); //
Fb=fopen(argv[3],"r"); //
if((!Fa)||(!Fb)) //
{ //
printf("Wrong input files.\n"); //
MPI_Abort(MPI_COMM_WORLD,-1); //
return 0; //
} //
for(i=0;i<N;i++) //
for(j=0;j<N;j++){ //
if((!fscanf(Fa,"%i",&A[i][j]))||(!fscanf(Fb,"%i",&B[j][i]))){
fprintf(stderr,"Wrong input matrix.\n");
fclose(Fa);
fclose(Fb);
MPI_Abort(MPI_COMM_WORLD,-1); //
} //
getc(Fa); //
getc(Fb); //
} //
} //
else { //
time_t T; //
T=time(NULL); //
srand((int)T); //
for(i=0;i<N;i++) //
for(j=0;j<N;j++){ //
A[i][j]=1;//new_rand(); //
B[i][j]=1;//new_rand(); //
} //
} //
for(i=0;i<numproc;i++) //
for(j=0;j<portion;j++){ //
MPI_Send(A[i*portion+j],N,MPI_INT,i,j,MPI_COMM_WORLD);
MPI_Send(B[i*portion+j],N,MPI_INT,i,j+portion,MPI_COMM_WORLD);
} //
} //
//====================================================================
for(i=0;i<numproc;i++)
if(myid==i)
for(j=0;j<portion;j++){
MPI_Recv(A1[j],N,MPI_INT,0,j,MPI_COMM_WORLD,&status);
MPI_Recv(B1[j],N,MPI_INT,0,j+portion,MPI_COMM_WORLD,&status);
}
//printf("Step2\n");
for(p=0;p<numproc;p++){
for(m=0;m<numproc;m++)
if(myid==m)
for(i=0;i<portion;i++)
for(j=0;j<portion;j++){
C1[i][ST[m*portion+j]]=0;
for(k=0;k<N;k++)
C1[i][ST[m*portion+j]]+=A1[i][k]*B1[j][k];
}
if(p!=numproc-1)
{
for(m=numproc-1;m>=0;m--)
if(myid==m){
if(myid!=numproc-1)
for(i=0;i<portion;i++)
MPI_Send(B1[i],N,MPI_INT,myid+1,i,MPI_COMM_WORLD);
else
for(i=0;i<portion;i++)
MPI_Send(B1[i],N,MPI_INT,0,i,MPI_COMM_WORLD);
if(m!=0)
for(i=0;i<portion;i++)
MPI_Recv(B1[i],N,MPI_INT,myid-1,i,MPI_COMM_WORLD, &status);
else
for(i=0;i<portion;i++)
MPI_Recv(B1[i],N,MPI_INT,numproc-1,i,MPI_COMM_WORLD, &status);
}
shift(ST,N,portion);
}
}
for(p=0;p<numproc;p++){
if(myid==p)
for(i=0;i<portion;i++)
MPI_Send(C1[i],N,MPI_INT,0,p*portion+i,MPI_COMM_WORLD);
}
if(myid==0){
for(p=0;p<numproc;p++)
for(i=0;i<portion;i++)
MPI_Recv(C[p*portion+i],N,MPI_INT,p,p*portion+i,MPI_COMM_WORLD,&status);
}
finish=MPI_Wtime();
if(myid==0)
Out(C,N,stdout);
if(myid==0)
printf("Time = %f.\n",finish-start);
MPI_Barrier(MPI_COMM_WORLD);
//MPI_Abort(MPI_COMM_WORLD,-1);
return 0;
}
|