Link to home
Start Free TrialLog in
Avatar of rbaian
rbaian

asked on

parallel (Matrix-matrix multiplication)

i have this code which is matrix-vector multiplication
i want to change it to Matrix-matrix multiplication

what change should i make?
if you have the code .... it is better.


--------------------------------------------
# include <sys/stdio.h>

# include <sys/types.h>

# include <sys/shm.h>

# include <sys/sem.h>

# include <sys/ipc.h>

# include "forkjoin.h"

# include "sharedlib.h"

# include "spinlock.h"



int main()
{

     int arr1[10][10];
  // Matrix Array

     int arr2[10];
      // Vector Array - Singular Column Matrix

     
     int *ansArr;
        // Multipication Answer Stored Here

                  // It need to be shared
     
             
     int shmid;
        // For ansArr

     
     int r1,c1;
         // Number of Rows and Columns of First Matrix

     int r2,c2=1;
       // Number of Rows and Columns of Second Matrix

     
     int iCount,jCount;

     
     int id;
            // Stores Process ID

     int nproc;
         // Number of Processes

     
     int sum;

     
     printf("Enter Number of Rows of First Matrix :");


     scanf("%d",&r1);

     
     printf("Enter Number of Columns of First Matrix :");

     scanf("%d",&c1);


     printf("Enter Number of Rows of Second Matrix :");

     scanf("%d",&r2);


     
     if(c1!=r2)

     {

          printf("Matrix Multipication is not Possible ...");

          exit(1);

     }

     

     
     // Initialize an Array    
     
     printf("\n\nEnter Values for Matrix ...\n");

     for(iCount=0;iCount<r1;iCount++)

     {

          for(jCount=0;jCount<c1;jCount++)

          {

          printf("Enter Value for Arr1[%d][%d] :",iCount,jCount);

               scanf("%d",&arr1[iCount][jCount]);

          }

     }
     
     printf("\n\nEnter Values for Vector Matrix ...\n");

     for(iCount=0;iCount<r2;iCount++)

     {

          printf("Enter Value for Arr2[%d] :",iCount);

          scanf("%d",&arr2[iCount]);

     }


     ansArr=(int*)sshared(sizeof(int)*r1,&shmid);

     
     nproc=r1;
     // Processes for Each Row Multipication

     
     id=process_fork(nproc);
     sum=0;

     for(iCount=0;iCount<c1;iCount++)

     {

          sum+=(arr1[id][iCount] * arr2[iCount]);

     }
     ansArr[id]=sum;
     
     process_join(nproc,id);

     
     printf("Array 1\n");

     
     for(iCount=0;iCount<r1;iCount++)

     {
          for(jCount=0;jCount<c1;jCount++)

          {

               printf("%d\t",arr1[iCount][jCount]);

          }
     
     printf("\n");

     }


     printf("Array 2 (Vector Matrix) \n");

     for(iCount=0;iCount<r1;iCount++)
     
{
          printf("%d\n",arr2[iCount]);

     }


     
     printf("Matrix-Vector Multipication \n");

     for(iCount=0;iCount<r1;iCount++)

     {

          printf("%d\n",ansArr[iCount]);

     }
     


     cleanup_memory(&shmid);
     
     
     return 0;

}
-----------------------------------------------------

/*
create and remove shared memory block
*/
void *sshared (int size,int size, int *shmid)
{


     *shmid=shmget ( IPC_PRIVATE, size,0666 | IPC_CREAT);

     
if (*shmid < 0)


     {


          printf("Error, cannot share memory");

          exit(0);

     }

              return shmat(*shmid,0,0);

  }




void cleanup_memory(int *shmid)

{

     struct shmid_ds *buf;


     if (shmctl(*shmid,IPC_RMID,buf) !=0)


     {

          printf("Error, cannot free memory");

          exit(0);
     }

}
------------------------------------------------
*    
      for locking the critical region
*/

void spin_lock_init(int *lok)

{
     int init_sem_value=1;
     *lok=semget(IPC_PRIVATE,1,(0600 | IPC_CREAT));
     
     if(*lok==-1)
     {
          perror("Error in Semget ...");
          exit(1);
     }
     
     if(semctl(*lok,0,SETVAL,init_sem_value) < 0)
     {
          perror("Error in Semctl ...");
          exit(1);
     }

}

void spin_lock(int *lok)
{
     struct sembuf sembuffer,*sops;
     sops= &sembuffer;
     sops->sem_num=0;
     sops->sem_op=-1;
     sops->sem_flg=0;
     
     if(semop(*lok,sops,1) < 0)
     {          
          perror("semop lock Error ...");
          exit(1);
     }    

}
void spin_unlock(int *lok)
{
     struct sembuf sembuffer,*sops;
     sops=&sembuffer;
     sops->sem_num=0;
     sops->sem_op=1;
     sops->sem_flg=0;
     
     if(semop(*lok,sops,1) < 0)
     {
          perror("semop Unlock Error ...");
          exit(1);
     }
}

void cleanup_semaphore(int *lok)
{
     if(semctl(*lok,1,IPC_RMID,0)  < 0)
     {
          perror("cleaning");
     }
}
-----------------------------------------------------

/*    
      process creation and process joining
*/



int process_fork(int newproc)
{


     int i;

     for(i=1;i<newproc;i++)

     {


          if(fork()==0)


               return i;


     }


     return 0;


}



int process_join(int newproc,int id)


{


     int i;

     if(id==0)

     {


          for(i=1;i<newproc;i++)

               wait(0);

     }

     else


          exit(0);

}
Avatar of Kelvin_King
Kelvin_King
Flag of Singapore image

for matrix X matrix multiplication you need to change a few things:

>>int arr2[10];
      // Vector Array - Singular Column Matrix

change to arr2[10][10];

>>int r2,c2=1;
       // Number of Rows and Columns of Second Matrix

change to int r2, c2;

and add one more line :

 printf("Enter Number of Columnss of Second Matrix :");

     scanf("%d",&c2);

That should help get you started. Anothre thing is, I don't think you should fix the array size to 10 x 10 at the begining.
You should initialize the array after you read in the rows and columns from the user. That'll make your program more robust.
Avatar of rbaian
rbaian

ASKER

i did all the change that you told me ..... but still matrix vector multiplication

i think i need more change here

(1) int *ansArr;
        // Multipication Answer Stored Here

(2) ansArr=(int*)sshared(sizeof(int)*r1,&shmid);

i tried to change 1&2 but there is error says: neither array nor pointer

ansArr=(int*)sshared(sizeof(int)*r1,&shmid);

should change to

ansArr=(int*)sshared(sizeof(int)*r1* c2,&shmid);

the ans matrix will have the same number of rows as the first matrix and numbe rof columns as the second matrix.


And there's more changes down the line.

Currently, each process handles only row, which corresponds to only 1 slot in the Answer array,

this time, each process has to handle all the columns for his row in the answer array. Since your array is an int pointer, you'll need to do some thing like this:

id=process_fork(nproc);
     sum=0;

     for(iCount=0;iCount<c2;iCount++) // for the number of columns in matrix2
     {
        for(jcount = 0; jCount < r2; jCount++)  //for the number of rows in matrix2
       {
          sum+=(arr1[id][jCount] * arr2[jCount][iCount]);
       }
     ansArr[(id * c2) +  iCount ]=sum;
     }

     process_join(nproc,id);
Avatar of rbaian

ASKER

Kelvin_King
i made change in this part

printf("Matrix-Vector Multipication \n");

     for(iCount=0;iCount<r1;iCount++)

     {

          printf("%d\n",ansArr[iCount]);

     }
     



i added another for statment and i used ansArr[(id * c2) +  iCount ] in printf but i got wrong result

can you explain  ansArr[(id * c2) +  iCount ]
is it to increase the space of the  ansArr

sorry, i made a mistake in my earlier code:

id=process_fork(nproc);
     sum=0;

     for(iCount=0;iCount<c2;iCount++) // for the number of columns in matrix2
     {
        for(jcount = 0; jCount < r2; jCount++)  //for the number of rows in matrix2
       {
          sum+=(arr1[id][jCount] * arr2[jCount][iCount]);
       }
     ansArr[(id * c2) +  iCount ]=sum;
     sum = 0; // see if it works now
     }

     process_join(nproc,id);

>> can you explain  ansArr[(id * c2) +  iCount ]

Basically, what I'm trying to do, is access each row in the ans matrix.

Since id represents the ith row, so to access i,j in the particular matrix. I multiply id by the number of columns in each row. So for example, if id = 3:  Then 3 * c2 will give me the first column in the 3rd row of the matrix, and then (3 * c2) + iCount will give me the next column and so on.

hope this is clearer.
Avatar of rbaian

ASKER

with this:
printf("Matrix-Matrix Multipication \n");

for(iCount=0;iCount<c2;iCount++) // for the number of columns in matrix2
     {
        for(jcount = 0; jCount < r2; jCount++)  //for the number of rows in matrix2
              {
                   printf("%d",ansArr[(id * c2) +  iCount ]);
            }
    }
-----------------------------------------------------------------
i tried  to multiply two of 2X2 matrices first one is  r1=1 1 & r2= 1 1 and  second matrix is r1=2 2 & r2= 2 2  the result : r1= 4 4 & r2= 8 8 which is wrong.

 
try this:

for(iCount=0;iCount<c2;iCount++) // for the number of columns in matrix2
     {
        for(jcount = 0; jCount < r2; jCount++)  //for the number of rows in matrix2
              {
                   printf("%d",ansArr[jCount]);
            }
    }
Avatar of rbaian

ASKER

still not working
ASKER CERTIFIED SOLUTION
Avatar of Kelvin_King
Kelvin_King
Flag of Singapore image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
remember to initialize the ansArr to 0 first.

Avatar of rbaian

ASKER

Kelvin king it is working now but my last question.......

can you explain how the code work in general ..... i want to be sure if i get it correctly
Glad to hear you got it working : )

Well, basically each process (id) will compute the resultant matrix for that row it's assigned to. Eg, process 0 will handle row 0, process 1 will handle row 1 etc.

So what the code is doing,  is it takes i,j meaning the number of columns in matrix 2 and number of rows in matrix 1, and computes the resultant row in the ans matrix for that process.

Is this clearer now ? Feel free to ask if you are unsure of anything.
Avatar of rbaian

ASKER

thank you ... kelvin king
Glad I could help : )