Kozinski123
Kozinski123

Reputation: 35

Parallel multiplication of two square matrices

My program is to multiply two matrices to produce a matrix, C. Everything works fine when I create a matrix to the size of 3x3 (9), but when I want to resize M and N = 4 (i.e. a 4x4 matrix), I get an error ArrayIndexOutOfBoundsException.

I tried to modify it many times but I still can't see my simple error. Could anyone tell me how I can modify the array to "automatically" adapt to the size of the matrix?

public class ParallelMultiplier {
    public static int M = 4;
    public static int N = 4;

    public static int[][] A = {{1, 4}, {2, 5}, {3, 6}};
    public static int[][] B = {{8, 7, 6}, {5, 4, 3}};
    public static int[][] C = new int[M][N];
    public static WorkerThread[][] Threads = new WorkerThread[3][3];

    public static void main(String[] args) {
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                Threads[i][j] = new WorkerThread(i, j, A, B, C);
                Threads[i][j].start();
            }
        }

        System.out.println("Elements of Matrix C:");
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                System.out.println("[" + i + "," + j + "] = " + C[i][j]);
            }
        }
    }
}

and Worker

class WorkerThread extends Thread {
    private int row;
    private int col;
    private int[][] A;
    private int[][] B;
    private int[][] C;

    public WorkerThread(int row, int col, int[][] A, int[][] B, int[][] C) {
        this.row = row;
        this.col = col;
        this.A = A;
        this.B = B;
        this.C = C;
    }

    public void run() {
        C[row][col] = (A[row][0] * B[0][col]) + (A[row][1] * B[1][col]);
    }
}

Upvotes: 1

Views: 376

Answers (1)

dreamcrash
dreamcrash

Reputation: 51413

You need more than just the variables M and N you need:

  1. Number of rows and cols of matrix A;
  2. Number of rows and cols of matrix B;
  3. Number of rows and cols of matrix C;

The values of 3. can be deduced based on the value of 1. and 2., namely:

  • The number of rows of matrix C is the same as the number of rows of matrix A;
  • The number of cols of matrix C is the same as the number of cols of matrix B;

my program is to multiply two matrix and display it in matrix C.

Your matrix multiplication algorithm is wrong, the sequential code should look like this:

for (int i = 0; i < rowsA; i++)
    for (int j = 0; j < colsB; j++)
        for (int k = 0; k < colsA; k++)
            C[i][j] += A[i][k] * B[k][j];

You need to also make sure that the matrices A and B can be multiple against each other, you cannot randomly set different sizes of those matrix. There is plenty of resources online that explain the constrains that matrix A and B must obey in order to A x B be possible.

If you statically set the matrices:

public static int[][] A = {{1, 4}, {2, 5}, {3, 6}};
public static int[][] B = {{8, 7, 6}, {5, 4, 3}};

assuming that each row of the matrices have the same size you can just use A.length and A[0].length to get the number of rows and columns, respectively. This way whenever you change the sizes of the matrices it will be immediately reflect on the code.

Finally, you need also to ensure that you wait for the threads to finish their work (e.g., calling join) before actually printing the values of the matrix C. For instance by doing:

for (int i = 0; i < M; i++)
    for (int j = 0; j < N; j++)
        Threads[i][j].join();

An untested running example:

class WorkerThread extends Thread {
    private final int row_a;
    private final int col_b;
    private final int col_a;
    private final int[][] A;
    private final int[][] B;
    private final int[][] C;

    public WorkerThread(int row_a, int col_b, int col_a,
                        int[][] A, int[][] B, int[][] C) {
        this.row_a = row_a;
        this.col_b = col_b;
        this.col_a = col_a;
        this.A = A;
        this.B = B;
        this.C = C;
    }

    public void run() {
        C[row_a][col_b] += A[row_a][col_a] * B[col_a][col_b];
    }
}
public class ParallelMultiplier {
    public static int[][] A = {{1, 4}, {2, 5}, {3, 6}};
    public static int[][] B = {{8, 7, 6}, {5, 4, 3}};
    public static int M = A.length;
    public static int N = B[0].length;
    public static int[][] C = new int[M][N];
    public static WorkerThread[][] Threads = new WorkerThread[M][N];

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < A.length; i++)
            for (int j = 0; j < B[0].length; j++)
                for (int k = 0; k < A[0].length; k++) {
                    Threads[i][j] = new WorkerThread(i, j, k, A, B, C);
                    Threads[i][j].start();
                }

        System.out.println("Wait for work to finish ");
        for (int i = 0; i < M; i++)
            for (int j = 0; j < N; j++)
                Threads[i][j].join();

        System.out.println("Elements of Matrix C:");
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {
                System.out.println("[" + i + "," + j + "] = " + C[i][j]);
            }
        }
    }
}

Upvotes: 2

Related Questions