0

I am building an application to solve Matrices in Linear Algebra. I have this class:

class Matrix:
def __init__(self):
    self.elements = []
    self.height = 0
    self.width = 0

def __add__(self, matrix):
    resultant_matrix = []
    row = []
    for i in range(self.height):
        row.clear()
        for j in range(self.width):
            row.insert(j, self.elements[i][j] + matrix.elements[i][j])
        resultant_matrix.insert(i, row)
    return self.list_to_object(resultant_matrix)

@staticmethod
def list_to_object(list_matrix):
    matrix_obj = Matrix()
    matrix_obj.elements = list_matrix
    matrix_obj.height = len(list_matrix)
    matrix_obj.width = len(list_matrix[0])
    return matrix_obj

@classmethod
def get_matrix(cls, rows=3, columns=3):
    mat = Matrix()
    for i in range(rows):
        row = []
        for j in range(columns):
            row.append(j)
        mat.elements.append(row)
    mat.height = len(mat.elements)
    mat.width = len(mat.elements[0])
    return mat

My focus is on the add method that helps me to add to matrices.

I have a method in the following class addition to split the matrices into smaller parts, then do the addition process on them, then reassemble them and return the new matrix.

class ThreadingManager:
threads = []
maximum_available_threads = 8

def do_add(self, slice1, slice2, index, _list):
    m1 = Matrix.list_to_object(slice1)
    m2 = Matrix.list_to_object(slice2)
    elements = (m1 + m2).elements
    for i, row in enumerate(elements):
        _list[index+i] = row

def addition(self, matrix_a, matrix_b):
    m1 = matrix_a.elements
    m2 = matrix_b.elements

    parts_number = self.maximum_available_threads

    sub_matrices_m2 = get_sub_matrix(m1, parts_number)
    sub_matrices_m3 = get_sub_matrix(m2, parts_number)
    new_list = [[] * matrix_a.width] * matrix_a.height

    for i in range(len(sub_matrices_m2)):
        sub_matrices_m2_i = sub_matrices_m2[i]
        sub_matrices_m3_i = sub_matrices_m3[i]
        rows_number_per_thread = i*len(sub_matrices_m2_i)
        thread = threading.Thread(target=self.do_add, args=(sub_matrices_m2_i, sub_matrices_m3_i,
                                                            rows_number_per_thread, new_list))
        thread.start()
        self.threads.append(thread)

    for thread in self.threads:
        thread.join()
        self.threads.remove(thread)
    return Matrix.list_to_object(new_list)

Finally, I have this test case (You can change the 50000 to any number, depending on your computer resources)

mat_a = Matrix.get_matrix(50000, 5)
mat_b = Matrix.get_matrix(50000, 5)

start = datetime.now()
mat_c = mat_a + mat_b
end = datetime.now()
print('time needed before multithreading is:', end - start)

start = datetime.now()
result = ThreadingManager().addition(mat_a, mat_b)
end = datetime.now()
print('time needed before multithreading is:', end - start)

My problem is that I cannot find any difference between the normal addition and multithreading. How can I use multithreading in a better way?

Note: If I removed the line row.clear() in the Matrix class, I have a wrong answer but I can notice the differences after multithreading

needed imports

import math
import threading
from datetime import datetime
Baghdadi
  • 25
  • 3
  • 1
    For Python, getting no speedup after multithreading a computation *is* the expected performance. :( https://stackoverflow.com/questions/1294382/what-is-the-global-interpreter-lock-gil-in-cpython – Jeremy Friesner May 05 '22 at 14:26

0 Answers0