умножение матрицы MPI для запуска с другим числом процессоров - PullRequest
0 голосов
/ 19 апреля 2020

Итак, я получил код, работающий при запуске на 1 процессе. Хотя, когда я пытаюсь запустить его на более чем 2 или более процессорах (mpirun -n 4) (mpirun -n 8) и т. Д .; половина моих результатов возвращается как ноль. Я предполагаю, потому что это не имеет отношения к случаю, когда число процессоров делится на размер матрицы. Любые идеи? Я пытаюсь инициализировать обе матрицы из командной строки и выполнить умножение матриц с использованием MPI. Я знал это и был бы рад любой помощи. Например, когда я ввожу размер 2 и инициализирую матрицу A для значений {1,4,6,7}, а матрицу B для {8,9,4,5}, мой результат получается {8,9, 0,0} ..

void init_Matrix(int n, int matrix[n][n])
{

  for(int i = 0; i < n; i++)
  {
    for(int j = 0; j < n; j++)
    {
      scanf("%i", &matrix[i][j]);
    }
  }
}


void printMatrix(int n, int matrix[n][n])
{
  for(int i = 0; i < n; i++)
  {
    for(int j = 0; j < n; j++)
    {
      printf("%d" , matrix[i][j]);
      printf(" ");
    }
    printf("\n");
  }
}

int main(int argc, char *argv[])
{
  MPI_Init(&argc, &argv);
  int rank, size;
  MPI_Comm_size(MPI_COMM_WORLD, &size); //num p
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  int n;
  if(rank == 0)
  {

    printf("Enter in size of matrix! \x0A");
    scanf("%i",&n);
  }

  MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD);
  int A[n][n];
  int B[n][n];
  int C[n][n];
  int aa[n/size][n];
  int cc[n/size][n];
if(rank == 0)
{
    init_Matrix(n,A);
    init_Matrix(n,B);
}
for(int i = 0; i < n; i++)
{
  for(int j = 0; j < n; j++)
  {
    cc[i][j] = 0;
  }
}
  //scatter rows of first matrix to different processes
  MPI_Scatter(A, n*n/size, MPI_INT, aa, n*n/size, MPI_INT,0,MPI_COMM_WORLD);
  //broadcast second matrix to all processes
  MPI_Bcast(B, n*n, MPI_INT, 0, MPI_COMM_WORLD);

  MPI_Barrier(MPI_COMM_WORLD);
  //perform vector multiplication by all processes
    for(int k = 0; k < n/size; k++)
    {
      for (int i = 0; i < n; i++)
      {
        for (int j = 0; j < n; j++)
        {
          cc[i][j] += A[i][k] * B[k][j];
        }
      }
    }

  MPI_Gather(cc, n*n/size, MPI_INT, C, n*n/size, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Barrier(MPI_COMM_WORLD);
  if(rank == 0){
    printMatrix(n, C);
  }
  MPI_Finalize();
}

обновлено: обновлена ​​попытка с использованием mpi scatterv и сборщика mpi

:


void initMatrix(int Size, int matrix[Size][Size])

{



  for(int i = 0; i < Size; i++)

  {

    for(int j = 0; j < Size; j++)

      scanf("%i", &matrix[i][j]);

  }

}



void multIJK(int Size, int A[Size][Size], int B[Size][Size], int pResult[Size])

{

  for(int i = 0; i < Size; i++)

  {

    for(int j = 0; j < Size; j++)

    {

      for(int k = 0; k < Size; k++)

        pResult += A[i][k] * B[k][j];

    }

  }

}

int main(int argc, char* argv[]) {

  int Size;

  int RowNum;

  int ProcNum;

  int ProcRank;

  MPI_Init(&argc, &argv);

  MPI_Comm_size(MPI_COMM_WORLD, &ProcNum);

  MPI_Comm_rank(MPI_COMM_WORLD, &ProcRank);



  if (ProcRank == 0) {     

    printf("Enter in size of matrix! \x0A"); 

    scanf("%i", &Size);

  }   

  int aMatrix[Size][Size];

  int bMatrix[Size][Size];





  MPI_Bcast(&Size, 1, MPI_INT, 0, MPI_COMM_WORLD);

  int RestRows = Size;  

  for (int i=0; i<ProcRank; i++)      

    RestRows = RestRows-RestRows/(ProcNum-i);   

  RowNum = RestRows/(ProcNum-ProcRank);

  int pResult[Size];   

  int pProcRows[RowNum*Size];   

  int pProcResult[RowNum];

  if(ProcRank == 0) 

  {

      initMatrix(Size,aMatrix);

      initMatrix(Size,bMatrix);

  } 



  RestRows=Size; // Number of rows, that haven’t been distributed yet

  MPI_Bcast(bMatrix, Size, MPI_DOUBLE, 0, MPI_COMM_WORLD);



  // Alloc memory for temporary objects  

  // the number of elements sent to the process   

  int pSendInd[ProcNum];  

 // the index of the first data element sent to the process   

 int pSendNum[ProcNum];



  // Define the disposition of the matrix rows for current process   

  RowNum = (Size/ProcNum);   

  pSendNum[0] = RowNum*Size;  

  pSendInd[0] = 0;   

  for (int i=1; i<ProcNum; i++) {    

    RestRows -= RowNum;     

    RowNum = RestRows/(ProcNum-i);     

    pSendNum[i] = RowNum*Size;    

    pSendInd[i] = pSendInd[i-1]+pSendNum[i-1]; 

  }



  // Scatter the rows  

  MPI_Scatterv(aMatrix , pSendNum, pSendInd, MPI_INT, pProcRows, 

      pSendNum[ProcRank], MPI_DOUBLE, 0, MPI_COMM_WORLD);



  multIJK(Size,aMatrix,bMatrix,pResult);



  RestRows=Size; // Number of rows, that haven’t been distributed yet



  //Alloc memory for temporary objects  

  // Number of elements, that current process sends  

  int pReceiveNum[ProcNum];   



  /* Index of the first element from current process in result vector */   

  int pReceiveInd[ProcNum];



  //Define the disposition of the result vector block of current processor  

  pReceiveInd[0] = 0;  

  pReceiveNum[0] = Size/ProcNum;  

  for (int i=1; i<ProcNum; i++) {  

    RestRows -= pReceiveNum[i-1];    

    pReceiveNum[i] = RestRows/(ProcNum-i);    

    pReceiveInd[i] = pReceiveInd[i-1]+pReceiveNum[i-1];  

  }   //Gather the whole result vector on every processor  

  MPI_Allgatherv(pProcResult, pReceiveNum[ProcRank], MPI_INT, pResult, 

      pReceiveNum, pReceiveInd, MPI_DOUBLE, MPI_COMM_WORLD);





  //ProcessTermination(aMatrix,bMatrix, pResult, pProcRows, pProcResult);

  if(ProcRank == 0)

  {

    for(int i = 0; i < Size; i++)

    {

      printf("%i\n",pResult[i]);

    }



  }

  MPI_Finalize();

}

1 Ответ

0 голосов
/ 19 апреля 2020

У вас есть проблемы с логикой c.

for(int i = 0; i < n; i++) <-- this should be until n/size, you are going into unallocated memory
{
   for(int j = 0; j < n; j++)
   {
     cc[i][j] = 0;
   }
}
cc[i][j] += A[i][k] * B[k][j]; <-- again, going outsize allocated memory

Замените его на

cc[k][i] += A[k][j] * B[j][i];

Надеемся, что это все проблемы.
Также следует учитывать случаи, когда размер матрицы не делится на число процессоров.

...