Multiplying a vector by a matrix
using MPI_Type_vector and MPI_Type_commit
and MPI_Gather (to collect the answers into one array)

  • Assignment: Use parallel programming techniques to find the product of a vector (1 row) times a matrix. The product of a vector and a matrix will be another vector (a 1 row array) storing the dot products of the the vector and each column in the matrix. Your answer will have as many dot products as there are columns in the array. The number of elements in the multiplying vector must be the same as the number of rows in the matrix.

    Using parallel programming, each process will find the dotproduct of the vector and the column of the matrix corresponding to the rank of each process. Process 0 uses column 0, process 1 uses column 1, etc.

    Use MPI_Type_vector to pass consecutive columns of the matrix to each process. Use MPI_Gather to collect the dot products from each process.

  • Background material

    vectormult.c is the shell program to use as an example of MPI_Type_vector
    gather.c is a shell program to use as an example of MPI_Gather

    1. Matrix x is
           10  20  30  40  50  60
           70  80  90 100 110 120
          130 140 150 160 170 180
          190 200 210 220 230 240
      

    2. Vector y is: 2 4 6 8

    3. The shell program uses a 4 row, 6 column auxiliary matrix w to pass only column 3:
       
             40
            100
            160
            220
         
      The above column (x[0][3]) is sent to process 1 from process 0. These four values are stored in process 1 in column w[][3]

      In process 1, matrix w is now:

         0  0  0   40  0  0
         0  0  0  100  0  0
         0  0  0  160  0  0
         0  0  0  220  0  0
       

    4. Process 1 finds the dot product of vector y and column 3 of auxiliary matrix w. In this example, the dot product can be thought of as multiplying the 4-element row vector y times the 4-element column vector w[0][3]:
         2 4 6 8   X    40       =     2 X 40 + 4 X 100 + 6 X 160 + 8 * 220
                       100               80  +  400  +  960  +  1760
                       160               3200
                       220
      
      
      The dot product of a row vector and a column vector is a single number, 3200 in this example

  • Assignment:

    1. Complete the program to find the entire matrix product of vector y multiplied by each column of matrix x. You will be finding the dot product of vector y times each column in matrix x
         2 4 6 8    X     10  20  30  40  50  60
                          70  80  90 100 110 120
                         130 140 150 160 170 180
                         190 200 210 220 230 240
      
      

    2. For example, using processes 0, 1, 2, 3, 4, and 5 to calculate the 6 dot products will look like the following. The answer will be a vector containing each of these dot products:
      Process 0 can use column 0 of matrix x:
      
         Find the dot product of y and x[][0] 
      
         [2 4 6 8] X 10
                     70
                    130
                    190        = 2600
      
      Process 1 receives column 1 from matrix x, stores this in column 1 of matrix w:
      
         w matrix will be:  0   20  0  0  0  0
                            0   80  0  0  0  0
                            0  140  0  0  0  0
                            0  200  0  0  0  0
      
          Find the dot product of y and w[][1] 
      
         [2 4 6 8] X 20
                     80
                    140
                    200        = 2800
      
      Process 2 receives column 2 from matrix x, stores this in column 2 of matrix w:
      
      
         w matrix will be:  0  0  30  0  0  0
                            0  0  90  0  0  0
                            0  0 140  0  0  0
                            0  0 210  0  0  0
      
          Find the dot product of y and w[][2] 
       
         [2 4 6 8] X 30
                     90
                    150
                    210      = 3000
      
      Process 3 receives column 3 from matrix x, stores this in column 3 of matrix w:
      
         w matrix will be:  0  0  0  40  0  0
                            0  0  0 100  0  0
                            0  0  0 150  0  0
                            0  0  0 220  0  0
      
          Find the dot product of y and w[][3] 
      
         [2 4 6 8] X 40
                    100
                    160
                    220     = 3200
      
      Process 4 receives column 4 from matrix x, stores this in column 4 of matrix w:
      
         w matrix will be:  0  0  0  0  50  0
                            0  0  0  0 110  0
                            0  0  0  0 160  0
                            0  0  0  0 230  0
      
          Find the dot product of y and w[][4] 
      
         [2 4 6 8] X 50
                    110
                    170
                    230   = 3400
      
      Process 5 receives column 5 from matrix x, stores this in column 5 of matrix w:
      
         w matrix will be:  0  0  0  0  0  60
                            0  0  0  0  0 120
                            0  0  0  0  0 170
                            0  0  0  0  0 240
      
          Find the dot product of y and w[][5] 
      
         [2 4 6 8] X 60
                    120
                    180
                    240   = 3600
      
      Use MPI_Gather to collect these dot products for the final answer. MPI_Gather puts the dot products into a vector in process 0, in this case a six element vector containing each of the dot products above: 2600 2800 3000 3200 3400 3600
  • Using MPI_Type_vector:

    In the call to MPI_Type_vector (see below) you are creating a pointer to a new MPI datatype that represents a column of a matrix.

       count = elements; block_length = 1; stride = 6;
    
       MPI_Type_vector(count,block_length,stride,MPI_INT,&pointer_to_new_mpi_type);
       /* commit the new datatype */
       MPI_Type_commit(&pointer_to_new_mpi_type);
    
       /* Root contains the elements. Send them to other processes */
       if (myrank==0)
              MPI_Send(&x[0][3],1,pointer_to_new_mpi_type,1,0,MPI_COMM_WORLD);
       else {
          /* Non-root processes receive the variables and print them */
          MPI_Recv(&x[0][3],1,pointer_to_new_mpi_type,0,0,MPI_COMM_WORLD,&status);
          printf("In process with rank %d\n",myrank);
          for(loop=0;loop¿elements;loop++){
             printf("\tx[%d][3]==> %d\n",loop,x[loop][3]);
          }
      }
    
      /* finish up */
      MPI_Type_free(&pointer_to_new_mpi_type);