# Multiplication of Matrix using threads

Last Updated : 20 May, 2024

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 1Matrix B 2 3 2 4 5 1 7 8 6Output : Multiplication of A and B2 3 24 5 17 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. ``` Python ```# 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(" ")); } ``` 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; } ```

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++ ```#include <iostream> #include <vector> std::vector<std::vector<int> > matrixMultiplication( const std::vector<std::vector<int> >& matA, const std::vector<std::vector<int> >& matB) { int rowsA = matA.size(); int colsA = matA[0].size(); int colsB = matB[0].size(); if (colsA != matB.size()) { throw std::invalid_argument( "Matrices cannot be multiplied: columns of " "matrix A must be equal to rows of matrix B"); } std::vector<std::vector<int> > result( rowsA, std::vector<int>(colsB, 0)); for (int i = 0; i < rowsA; i++) { for (int j = 0; j < colsB; j++) { int sum = 0; for (int k = 0; k < colsA; k++) { sum += matA[i][k] * matB[k][j]; } result[i][j] = sum; } } return result; } int main() { // Example matrices std::vector<std::vector<int> > matA = { { 3, 7, 3, 6 }, { 9, 2, 0, 3 }, { 0, 2, 1, 7 }, { 2, 2, 7, 9 } }; std::vector<std::vector<int> > matB = { { 6, 5, 5, 2 }, { 1, 7, 9, 6 }, { 6, 6, 8, 9 }, { 0, 3, 5, 2 } }; // Perform matrix multiplication std::vector<std::vector<int> > result = matrixMultiplication(matA, matB); // Display the result std::cout << "Multiplication of A and B:" << std::endl; for (const auto& row : result) { for (int num : row) { std::cout << num << " "; } std::cout << std::endl; } return 0; } ``` C ```// C Program to multiply two matrix using pthreads without // use of global variables #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.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; } ``` Java ```import java.util.Random; class MatrixMultiplier implements Runnable { private final int[][] matA; private final int[][] matB; private final int row; private final int col; private final int[] resultRow; public MatrixMultiplier(int[][] matA, int[][] matB, int row, int col, int[] resultRow) { this.matA = matA; this.matB = matB; this.row = row; this.col = col; this.resultRow = resultRow; } @Override public void run() { int sum = 0; for (int i = 0; i < matA[0].length; i++) { sum += matA[row][i] * matB[i][col]; } resultRow[col] = sum; } } public class MatrixMultiplication { public static void main(String[] args) throws InterruptedException { final int MAX = 4; int[][] matA = new int[MAX][MAX]; int[][] matB = new int[MAX][MAX]; int[][] result = new int[MAX][MAX]; Random rand = new Random(); // Generating random values in matA for (int i = 0; i < MAX; i++) { for (int j = 0; j < MAX; j++) { matA[i][j] = rand.nextInt(10); } } // Generating random values in matB for (int i = 0; i < MAX; i++) { for (int j = 0; j < MAX; j++) { matB[i][j] = rand.nextInt(10); } } // Displaying matA System.out.println("Matrix A:"); for (int[] row : matA) { for (int val : row) { System.out.print(val + " "); } System.out.println(); } // Displaying matB System.out.println("Matrix B:"); for (int[] row : matB) { for (int val : row) { System.out.print(val + " "); } System.out.println(); } Thread[][] threads = new Thread[MAX][MAX]; // Multiplying matrices for (int i = 0; i < MAX; i++) { for (int j = 0; j < MAX; j++) { threads[i][j] = new Thread(new MatrixMultiplier( matA, matB, i, j, result[i])); threads[i][j].start(); } } // Waiting for all threads to finish for (int i = 0; i < MAX; i++) { for (int j = 0; j < MAX; j++) { threads[i][j].join(); } } // Displaying result matrix System.out.println("Resultant Matrix:"); for (int[] row : result) { for (int val : row) { System.out.print(val + " "); } System.out.println(); } } } ``` Python ```import threading import random MAX = 4 # Function to multiply two matrices def multiply(data): result = 0 x = data[0] for i in range(1, x + 1): result += data[i] * data[i + x] return result # Thread function def mult_thread(data, results, index): result = multiply(data) results[index] = result # Main function def main(): matA = [[random.randint(0, 9) for _ in range(MAX)] for _ in range(MAX)] matB = [[random.randint(0, 9) for _ in range(MAX)] for _ in range(MAX)] # Displaying matA print("Matrix A:") for row in matA: print(row) # Displaying matB print("\nMatrix B:") for row in matB: print(row) results = [None] * (MAX * MAX) threads = [] count = 0 for i in range(MAX): for j in range(MAX): # Storing row and column elements in data data = [MAX] + matA[i] + [row[j] for row in matB] # Creating thread thread = threading.Thread( target=mult_thread, args=(data, results, count)) thread.start() threads.append(thread) count += 1 # Waiting for all threads to complete for thread in threads: thread.join() print("\nResultant Matrix:") for i, result in enumerate(results): print(result, end=" ") if (i + 1) % MAX == 0: print() if __name__ == "__main__": main() ``` JavaScript ```function matrixMultiplication(matA, matB) { const rowsA = matA.length; const colsA = matA[0].length; const colsB = matB[0].length; if (colsA !== matB.length) { throw new Error("Matrices cannot be multiplied: columns of matrix A must be equal to rows of matrix B"); } const result = new Array(rowsA).fill(0).map(() => new Array(colsB).fill(0)); for (let i = 0; i < rowsA; i++) { for (let j = 0; j < colsB; j++) { let sum = 0; for (let k = 0; k < colsA; k++) { sum += matA[i][k] * matB[k][j]; } result[i][j] = sum; } } return result; } // Example matrices const matA = [ [3, 7, 3, 6], [9, 2, 0, 3], [0, 2, 1, 7], [2, 2, 7, 9] ]; const matB = [ [6, 5, 5, 2], [1, 7, 9, 6], [6, 6, 8, 9], [0, 3, 5, 2] ]; // Perform matrix multiplication const result = matrixMultiplication(matA, matB); // Display the result console.log("Multiplication of A and B:"); result.forEach(row => console.log(row.join(" "))); ```

Output:Â

`Matrix A3 7 3 6 9 2 0 3 0 2 1 7 2 2 7 9Matrix B6 5 5 2 1 7 9 6 6 6 8 9 0 3 5 2 Multiplication of A and B43 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)

Share your thoughts in the comments