Open In App

Multiplication of Matrix using threads

Last Updated : 25 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Multiplication of matrix does take time surely. Time complexity of matrix multiplication is O(n^3) using normal matrix multiplication. And Strassen algorithm improves it and its time complexity is O(n^(2.8074)).

But, Is there any way to improve the performance of matrix multiplication using the normal method. 

Multi-threading can be done to improve it. In multi-threading, instead of utilizing a single core of your processor, we utilizes all or more core to solve the problem.
We create different threads, each thread evaluating some part of matrix multiplication. 

Depending upon the number of cores your processor has, you can create the number of threads required. Although you can create as many threads as you need, a better way is to create each thread for one core.

In second approach,we create a separate thread for each element in resultant matrix. Using pthread_exit() we return computed value from each thread which is collected by pthread_join(). This approach does not make use of any global variables.

Examples: 

Input : 
Matrix A
 1 0 0
 0 1 0
 0 0 1

Matrix B
 2 3 2
 4 5 1
 7 8 6

Output : Multiplication of A and B
2 3 2
4 5 1
7 8 6

NOTE* It is advised to execute the program in linux based system 
Compile in linux using following code: 

g++ -pthread program_name.cpp

Implementation:

Java




import java.util.Random;
 
public class MatrixMultiplication {
    static final int MAX = 4;
    static final int MAX_THREAD = 4;
    static int[][] matA = new int[MAX][MAX];
    static int[][] matB = new int[MAX][MAX];
    static int[][] matC = new int[MAX][MAX];
    static int step_i = 0;
 
    static class Worker implements Runnable {
        int i;
 
        Worker(int i) {
            this.i = i;
        }
 
        @Override
        public void run() {
            for (int j = 0; j < MAX; j++) {
                for (int k = 0; k < MAX; k++) {
                    matC[i][j] += matA[i][k] * matB[k][j];
                }
            }
        }
    }
 
    public static void main(String[] args) {
        Random rand = new Random();
 
        // Generating random values in matA and matB
        for (int i = 0; i < MAX; i++) {
            for (int j = 0; j < MAX; j++) {
                matA[i][j] = rand.nextInt(10);
                matB[i][j] = rand.nextInt(10);
            }
        }
 
        // Displaying matA
        System.out.println("Matrix A");
        for (int i = 0; i < MAX; i++) {
            for (int j = 0; j < MAX; j++) {
                System.out.print(matA[i][j] + " ");
            }
            System.out.println();
        }
 
        // Displaying matB
        System.out.println("Matrix B");
        for (int i = 0; i < MAX; i++) {
            for (int j = 0; j < MAX; j++) {
                System.out.print(matB[i][j] + " ");
            }
            System.out.println();
        }
 
        // declaring four threads
        Thread[] threads = new Thread[MAX_THREAD];
 
        // Creating four threads, each evaluating its own part
        for (int i = 0; i < MAX_THREAD; i++) {
            threads[i] = new Thread(new Worker(step_i++));
            threads[i].start();
        }
 
        // joining and waiting for all threads to complete
        for (int i = 0; i < MAX_THREAD; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
 
        // Displaying the result matrix
        System.out.println("Multiplication of A and B");
        for (int i = 0; i < MAX; i++) {
            for (int j = 0; j < MAX; j++) {
                System.out.print(matC[i][j] + " ");
            }
            System.out.println();
        }
    }
}
// This code is written by Sundaram.


C++14




// CPP Program to multiply two matrix using pthreads
#include <bits/stdc++.h>
using namespace std;
 
// maximum size of matrix
#define MAX 4
 
// maximum number of threads
#define MAX_THREAD 4
 
int matA[MAX][MAX];
int matB[MAX][MAX];
int matC[MAX][MAX];
int step_i = 0;
 
void* multi(void* arg)
{
    int i = step_i++; //i denotes row number of resultant matC
   
    for (int j = 0; j < MAX; j++)
      for (int k = 0; k < MAX; k++)
        matC[i][j] += matA[i][k] * matB[k][j];
}
 
// Driver Code
int main()
{
    // Generating random values in matA and matB
    for (int i = 0; i < MAX; i++) {
        for (int j = 0; j < MAX; j++) {
            matA[i][j] = rand() % 10;
            matB[i][j] = rand() % 10;
        }
    }
 
    // Displaying matA
    cout << endl
         << "Matrix A" << endl;
    for (int i = 0; i < MAX; i++) {
        for (int j = 0; j < MAX; j++)
            cout << matA[i][j] << " ";
        cout << endl;
    }
 
    // Displaying matB
    cout << endl
         << "Matrix B" << endl;
    for (int i = 0; i < MAX; i++) {
        for (int j = 0; j < MAX; j++)
            cout << matB[i][j] << " ";       
        cout << endl;
    }
 
    // declaring four threads
    pthread_t threads[MAX_THREAD];
 
    // Creating four threads, each evaluating its own part
    for (int i = 0; i < MAX_THREAD; i++) {
        int* p;
        pthread_create(&threads[i], NULL, multi, (void*)(p));
    }
 
    // joining and waiting for all threads to complete
    for (int i = 0; i < MAX_THREAD; i++)
        pthread_join(threads[i], NULL);   
 
    // Displaying the result matrix
    cout << endl
         << "Multiplication of A and B" << endl;
    for (int i = 0; i < MAX; i++) {
        for (int j = 0; j < MAX; j++)
            cout << matC[i][j] << " ";       
        cout << endl;
    }
    return 0;
}


Python3




# Python3 Program to multiply two matrix using multi-threading
from threading import Thread
 
MAX = 4
MAX_THREAD = 4
 
matC = [[0 for i in range(MAX)] for j in range(MAX)]
step_i = 0
 
# Function to print matrix in readable format
def printMatrix(mat):
  for row in mat:
    print(row)
 
# Function to multiply a row of matrix A
# with entire matrix B to get a row of matrix C
def multi():
  global step_i, matC
  i = step_i
  step_i = step_i + 1
  for j in range(MAX):
    for k in range(MAX):
      matC[i][j] = matC[i][j] + matA[i][k] * matB[k][j]
 
if __name__ == "__main__":
  # matrix A used for muliplication
  matA = [[3,7,3,6],
          [9,2,0,3],
          [0,2,1,7],
          [2,2,7,9]]
   
  # matrix B used for multiplication
  matB = [[6,5,5,2],
          [1,7,9,6],
          [6,6,8,9],
          [0,3,5,2]]
  # creating list of size MAX_THREAD
  thread = list(range(MAX_THREAD))
  # creating MAX_THEAD number of threads
  for i in range(MAX_THREAD):
    thread[i] = Thread(target=multi)
    thread[i].start()
     
  # Waiting for all threads to finish
  for i in range(MAX_THREAD):
    thread[i].join()
     
  # Printing the resultant matrix C = A x B
  printMatrix(matC)


C#




using System;
using System.Threading;
 
public class MatrixMultiplication
{
    static readonly int MAX = 4;
    static readonly int MAX_THREAD = 4;
    static int[,] matA = new int[MAX, MAX];
    static int[,] matB = new int[MAX, MAX];
    static int[,] matC = new int[MAX, MAX];
    static int step_i = 0;
 
    class Worker
    {
        int i;
 
        public Worker(int i)
        {
            this.i = i;
        }
 
        public void Run()
        {
            for (int j = 0; j < MAX; j++)
            {
                for (int k = 0; k < MAX; k++)
                {
                    matC[i, j] += matA[i, k] * matB[k, j];
                }
            }
        }
    }
 
    public static void Main(string[] args)
    {
        Random rand = new Random();
 
        // Generating random values in matA and matB
        for (int i = 0; i < MAX; i++)
        {
            for (int j = 0; j < MAX; j++)
            {
                matA[i, j] = rand.Next(10);
                matB[i, j] = rand.Next(10);
            }
        }
 
        // Displaying matA
        Console.WriteLine("Matrix A");
        for (int i = 0; i < MAX; i++)
        {
            for (int j = 0; j < MAX; j++)
            {
                Console.Write(matA[i, j] + " ");
            }
            Console.WriteLine();
        }
 
        // Displaying matB
        Console.WriteLine("Matrix B");
        for (int i = 0; i < MAX; i++)
        {
            for (int j = 0; j < MAX; j++)
            {
                Console.Write(matB[i, j] + " ");
            }
            Console.WriteLine();
        }
 
        // declaring four threads
        Thread[] threads = new Thread[MAX_THREAD];
 
        // Creating four threads, each evaluating its own part
        for (int i = 0; i < MAX_THREAD; i++)
        {
            threads[i] = new Thread(new Worker(step_i++).Run);
            threads[i].Start();
        }
 
        // joining and waiting for all threads to complete
        for (int i = 0; i < MAX_THREAD; i++)
        {
            threads[i].Join();
        }
 
        // Displaying the result matrix
        Console.WriteLine("Multiplication of A and B");
        for (int i = 0; i < MAX; i++)
        {
            for (int j = 0; j < MAX; j++)
            {
                Console.Write(matC[i, j] + " ");
            }
            Console.WriteLine();
        }
    }
}


Javascript




const MAX = 4;
const MAX_THREAD = 4;
const matA = new Array(MAX).fill().map(() => new Array(MAX).fill(0));
const matB = new Array(MAX).fill().map(() => new Array(MAX).fill(0));
const matC = new Array(MAX).fill().map(() => new Array(MAX).fill(0));
let step_i = 0;
 
class Worker {
    constructor(i) {
        this.i = i;
    }
 
    run() {
        for (let j = 0; j < MAX; j++) {
            for (let k = 0; k < MAX; k++) {
                matC[this.i][j] += matA[this.i][k] * matB[k][j];
            }
        }
    }
}
 
// Generating random values in matA and matB
for (let i = 0; i < MAX; i++) {
    for (let j = 0; j < MAX; j++) {
        matA[i][j] = Math.floor(Math.random() * 10);
        matB[i][j] = Math.floor(Math.random() * 10);
    }
}
 
// Displaying matA
console.log("Matrix A");
for (let i = 0; i < MAX; i++) {
    console.log(matA[i].join(" "));
}
 
// Displaying matB
console.log("Matrix B");
for (let i = 0; i < MAX; i++) {
    console.log(matB[i].join(" "));
}
 
// declaring four threads
const threads = new Array(MAX_THREAD).fill();
 
// Creating four threads, each evaluating its own part
for (let i = 0; i < MAX_THREAD; i++) {
    threads[i] = new Worker(step_i++);
    threads[i].run();
}
 
// Displaying the result matrix
console.log("Multiplication of A and B");
for (let i = 0; i < MAX; i++) {
    console.log(matC[i].join(" "));
}


Output

Matrix A
7 2 6 8 
7 0 6 6 
6 1 7 5 
3 7 7 2 
Matrix B
3 5 3 6 
5 7 5 8 
8 9 4 9 
6 5 7 2 
Multiplication of A and B
127 143 111 128 
105 119 87 108 
109 125 86 117 
112 137 86 141 

Time Complexity: O(1)
Auxiliary Space: O(1)

An approach without using global variables:

NOTE* It is advised to execute the program in linux based system 

Compile in linux using following code: 

g++ -pthread program_name.cpp

Implementation:

C




// C Program to multiply two matrix using pthreads without
// use of global variables
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
#define MAX 4
 
 
//Each thread computes single element in the resultant matrix
void *mult(void* arg)
{
    int *data = (int *)arg;
    int k = 0, i = 0;
     
    int x = data[0];
    for (i = 1; i <= x; i++)
           k += data[i]*data[i+x];
     
    int *p = (int*)malloc(sizeof(int));
         *p = k;
     
//Used to terminate a thread and the return value is passed as a pointer
    pthread_exit(p);
}
 
//Driver code
int main()
{
 
    int matA[MAX][MAX];
    int matB[MAX][MAX];
     
     
    int r1=MAX,c1=MAX,r2=MAX,c2=MAX,i,j,k;
 
 
    // Generating random values in matA
    for (i = 0; i < r1; i++)
            for (j = 0; j < c1; j++)
                   matA[i][j] = rand() % 10;
           
        // Generating random values in matB
    for (i = 0; i < r1; i++)
            for (j = 0; j < c1; j++)
                   matB[i][j] = rand() % 10;
    
    // Displaying matA        
    for (i = 0; i < r1; i++){
        for(j = 0; j < c1; j++)
            printf("%d ",matA[i][j]);
        printf("\n");
    }
             
    // Displaying matB               
    for (i = 0; i < r2; i++){
        for(j = 0; j < c2; j++)
            printf("%d ",matB[i][j]);
        printf("\n");   
    }
     
     
    int max = r1*c2;
     
     
    //declaring array of threads of size r1*c2       
    pthread_t *threads;
    threads = (pthread_t*)malloc(max*sizeof(pthread_t));
     
    int count = 0;
    int* data = NULL;
    for (i = 0; i < r1; i++)
        for (j = 0; j < c2; j++)
               {
                
               //storing row and column elements in data
            data = (int *)malloc((20)*sizeof(int));
            data[0] = c1;
     
            for (k = 0; k < c1; k++)
                data[k+1] = matA[i][k];
     
            for (k = 0; k < r2; k++)
                data[k+c1+1] = matB[k][j];
              
             //creating threads
                pthread_create(&threads[count++], NULL,
                               mult, (void*)(data));
                 
                    }
     
    printf("RESULTANT MATRIX IS :- \n");
    for (i = 0; i < max; i++)
    {
      void *k;
       
      //Joining all threads and collecting return value
      pthread_join(threads[i], &k);
            
           
          int *p = (int *)k;
      printf("%d ",*p);
      if ((i + 1) % c2 == 0)
          printf("\n");
    }
 
     
 
  return 0;
}


Output: 

Matrix A
3 7 3 6 
9 2 0 3 
0 2 1 7 
2 2 7 9

Matrix B
6 5 5 2 
1 7 9 6 
6 6 8 9 
0 3 5 2 

Multiplication of A and B
43 100 132 87 
56 68 78 36 
8 41 61 35 
56 93 129 97 

Time Complexity: O(MAX*MAX)
Auxiliary Space: O(MAX*MAX)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads