Friday, November 8, 2013

Matrix multiplication using threads in Java

Implement a multithreaded version of matrix multiplication. The normal method for multiplying two such matrices involves performing all the calculations in the main thread. Each element (i,j) of the product matrix is obtained by multiplying the ith row of the first matrix with the jth column of the second. In the multi-threaded version, you will divide this computation among threads to achieve parallelism. Initialize two 3X3 matrices with random values. Create 3 threads. Each thread will compute 1/3rd of the product matrix. So the first thread calculates the product elements for the first row, the second for the next row and so on. The main thread should wait for all the threads to complete, and then print the resultant product matrix. Verify that this produces the same result as the normal method.

Solution:

import java.util.Random;

public class MatrixMultiplication {
    
    //Creating the matrix
    static int[][] mat = new int[3][3];
    static int[][] mat2 = new int[3][3];
    static int[][] result = new int[3][3];

    public static void main(String [] args){
        
        //Creating the object of random class
        Random rand = new Random();
        
        
        //Filling first matrix with random values
        for (int i = 0; i < mat.length; i++) {
            for (int j = 0; j < mat[i].length; j++) {
                mat[i][j]=rand.nextInt(10);
            }
        }
        
        //Filling second matrix with random values
        for (int i = 0; i < mat2.length; i++) {
            for (int j = 0; j < mat2[i].length; j++) {
                mat2[i][j]=rand.nextInt(10);
            }
        }

        //Printing the first matrix
        System.out.println("This is first matrix:");
        for (int i = 0; i < mat.length; i++) {
            for (int j = 0; j < mat[i].length; j++) {
                System.out.print(mat[i][j]+" ");
            }
            System.out.println();
        }

        //Printing the second matrix
        System.out.println("\nThis is second matrix:");
        for (int i = 0; i < mat.length; i++) {
            for (int j = 0; j < mat[i].length; j++) {
                System.out.print(mat2[i][j]+" ");
            }
            System.out.println();
        }

        try{
            //Object of multiply Class
            Multiply multiply = new Multiply(3,3);
            
            //Threads
            MatrixMultiplier thread1 = new MatrixMultiplier(multiply);
            MatrixMultiplier thread2 = new MatrixMultiplier(multiply);
            MatrixMultiplier thread3 = new MatrixMultiplier(multiply);
            
            //Implementing threads
            Thread th1 = new Thread(thread1);
            Thread th2 = new Thread(thread2);
            Thread th3 = new Thread(thread3);
            
            //Starting threads
            th1.start();
            th2.start();
            th3.start();
            
            th1.join();
            th2.join();
            th3.join();
            
        }catch (Exception e) {
            e.printStackTrace();
        }

        //Printing the result
        System.out.println("\n\nResult:");
        for (int i = 0; i < result.length; i++) {
            for (int j = 0; j < result[i].length; j++) {
                System.out.print(result[i][j]+" ");
            }
            System.out.println();
        }
    }//End main

}//End Class

//Multiply Class
class Multiply extends MatrixMultiplication {
    
    private int i;
    private int j;
    private int chance;
    
    public Multiply(int i, int j){
        this.i=i;
        this.j=j;
        chance=0;
    }
    
    //Matrix Multiplication Function
    public synchronized void multiplyMatrix(){
        
        int sum=0;
        int a=0;
        for(a=0;a<i;a++){
            sum=0;
            for(int b=0;b<j;b++){
                sum=sum+mat[chance][b]*mat2[b][a];
            }
            result[chance][a]=sum;
        }
        
        if(chance>=i)
            return;
        chance++;
    }
}//End multiply class

//Thread Class
class MatrixMultiplier implements Runnable {
    
    private final Multiply mul;
    
    public MatrixMultiplier(Multiply mul){
        this.mul=mul;
    }

    @Override
    public void run() {
        mul.multiplyMatrix();
    }
}


1 comment:

  1. I have applied this code. I tried it multiplying 1000x1000 length two matrices. Results are surprising: If I use 1 thread it takes ~80 ms and if I use 2 threads it takes ~100 ms. I did not stop, I tried 4 threads and guess what? It takes ~166 ms. What do you think about this situation?

    ReplyDelete