簡體   English   中英

如何將 MPI 阻塞代碼轉換為非阻塞代碼

[英]How to convert MPI blocking code into non blocking

我想執行矩陣乘法。 我必須編寫兩個代碼,一個是 MPI 阻塞,另一個是 MPI 非阻塞。 我已經完成了 MPI 阻塞。 我需要一些幫助來將下面的代碼轉換為 MPI 非阻塞。

這是帶有阻塞的矩陣乘法代碼,我想將其轉換為 MPI 非阻塞。 如果有人有空請回復..

 #include <stdlib.h>
#include <stdio.h>
#include "mpi.h"
#include <time.h>
#include <sys/time.h>
    

// Number of rows and columnns in a matrix
#define N 4

MPI_Status status;

// Matrix holders are created
double matrix_a[N][N],matrix_b[N][N],matrix_c[N][N];

int main(int argc, char **argv)
{
  int processCount, processId, slaveTaskCount, source, dest, rows, offset;

  struct timeval start, stop;

// MPI environment is initialized
  MPI_Init(&argc, &argv);
// Each process gets unique ID (rank)
  MPI_Comm_rank(MPI_COMM_WORLD, &processId);
// Number of processes in communicator will be assigned to variable -> processCount
  MPI_Comm_size(MPI_COMM_WORLD, &processCount);

// Number of slave tasks will be assigned to variable -> slaveTaskCount
  slaveTaskCount = processCount - 1;

// Root (Master) process
 if (processId == 0) {
    
// Matrix A and Matrix B both will be filled with random numbers
    srand ( time(NULL) );
    for (int i = 0; i<N; i++) {
      for (int j = 0; j<N; j++) {
        matrix_a[i][j]= rand()%10;
        matrix_b[i][j]= rand()%10;
      }
    }
    
  printf("\n\t\tMatrix - Matrix Multiplication using MPI\n");

// Print Matrix A
    printf("\nMatrix A\n\n");
    for (int i = 0; i<N; i++) {
      for (int j = 0; j<N; j++) {
        printf("%.0f\t", matrix_a[i][j]);
      }
        printf("\n");
    }

// Print Matrix B
    printf("\nMatrix B\n\n");
    for (int i = 0; i<N; i++) {
      for (int j = 0; j<N; j++) {
        printf("%.0f\t", matrix_b[i][j]);
      }
        printf("\n");
    }


    rows = N/slaveTaskCount;

    offset = 0;


    for (dest=1; dest <= slaveTaskCount; dest++)
    {
      // Acknowledging the offset of the Matrix A
      MPI_Send(&offset, 1, MPI_INT, dest, 1, MPI_COMM_WORLD);
      // Acknowledging the number of rows
      MPI_Send(&rows, 1, MPI_INT, dest, 1, MPI_COMM_WORLD);
      // Send rows of the Matrix A which will be assigned to slave process to compute
      MPI_Send(&matrix_a[offset][0], rows*N, MPI_DOUBLE,dest,1, MPI_COMM_WORLD);
      // Matrix B is sent
      MPI_Send(&matrix_b, N*N, MPI_DOUBLE, dest, 1, MPI_COMM_WORLD);
      
      // Offset is modified according to number of rows sent to each process
      offset = offset + rows;
    }


    for (int i = 1; i <= slaveTaskCount; i++)
    {
      source = i;
      // Receive the offset of particular slave process
      MPI_Recv(&offset, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status);
      // Receive the number of rows that each slave process processed
      MPI_Recv(&rows, 1, MPI_INT, source, 2, MPI_COMM_WORLD, &status);
      // Calculated rows of the each process will be stored int Matrix C according to their offset and
      // the processed number of rows
      MPI_Recv(&matrix_c[offset][0], rows*N, MPI_DOUBLE, source, 2, MPI_COMM_WORLD, &status);
    }

// Print the result matrix
    printf("\nResult Matrix C = Matrix A * Matrix B:\n\n");
    for (int i = 0; i<N; i++) {
      for (int j = 0; j<N; j++)
        printf("%.0f\t", matrix_c[i][j]);
      printf ("\n");
    }
    printf ("\n");
  }

// Slave Processes 
  if (processId > 0) {

    // Source process ID is defined
    source = 0;

    MPI_Recv(&offset, 1, MPI_INT, source, 1, MPI_COMM_WORLD, &status);
    // The slave process receives number of rows sent by root process  
    MPI_Recv(&rows, 1, MPI_INT, source, 1, MPI_COMM_WORLD, &status);
    // The slave process receives the sub portion of the Matrix A which assigned by Root 
    MPI_Recv(&matrix_a, rows*N, MPI_DOUBLE, source, 1, MPI_COMM_WORLD, &status);
    // The slave process receives the Matrix B
    MPI_Recv(&matrix_b, N*N, MPI_DOUBLE, source, 1, MPI_COMM_WORLD, &status);

    // Matrix multiplication

    for (int k = 0; k<N; k++) {
      for (int i = 0; i<rows; i++) {
        // Set initial value of the row summataion
        matrix_c[i][k] = 0.0;
        // Matrix A's element(i, j) will be multiplied with Matrix B's element(j, k)
        for (int j = 0; j<N; j++)
          matrix_c[i][k] = matrix_c[i][k] + matrix_a[i][j] * matrix_b[j][k];
      }
    }

   
    // value in matrix C 
    MPI_Send(&offset, 1, MPI_INT, 0, 2, MPI_COMM_WORLD);
    // Number of rows the process calculated will be sent to root process
    MPI_Send(&rows, 1, MPI_INT, 0, 2, MPI_COMM_WORLD);
    // Resulting matrix with calculated rows will be sent to root process
    MPI_Send(&matrix_c, rows*N, MPI_DOUBLE, 0, 2, MPI_COMM_WORLD);
  }

  MPI_Finalize();
}

以這種方式看待非阻塞:不是拼寫“現在我發送這個,現在你收到那個”,而是在計算階段決定:“這里將傳達的所有消息是什么”。 然后你對所有的發送做一個Irecv ,對所有相應的接收做一個Isend 然后等待所有結果請求。

一個問題是這些Isend/Irecv操作中的每一個都需要自己的緩沖區,因此您可能需要分配更多內存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM