DulcetAirman icon

Matrix Multiplication with Fork/Join

DulcetAirman | PRO | 08/23/19 03:46:21 PM UTC | 0 ⭐ | 1268 👁️ | Never ⏰ | []
Java |

2.95 KB

|

None

|

0 👍

/

0 👎

package com.example.foo;
 
import java.util.Arrays;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
 
/**
 * https://humanoidreadable.wordpress.com/2014/12/31/forkjoin-nonrecursive-task/
 * 
 * @author Claude Martin
 *
 */
public final class SomeClass {
    /** This is used to fork/join once per entry of the resulting matrix. */
    private static class MatrixProduct extends ForkJoinTask<int[][]> {
        private static final long serialVersionUID = 1527639909439152978L;
        private final int[][] A;
        private final int[][] B;
        private int[][] result = null;
 
        public MatrixProduct(final int[][] A, final int[][] B) {
            this.A = A;
            this.B = B;
        }
 
        @Override
        public int[][] getRawResult() {
            return result;
        }
 
        @Override
        protected void setRawResult(final int[][] value) {
            this.result = value;
        }
 
        // see https://en.wikipedia.org/wiki/Matrix_multiplication#Definition
        @Override
        protected boolean exec() {
            final int n = A.length;
            final int p = B[0].length;
            final int m = B.length; // == A[0].length
            this.result = new int[n][p];
            @SuppressWarnings("unchecked")
            final ForkJoinTask<Integer>[][] tasks = new ForkJoinTask[n][p];
            if (m != A[0].length) {
                throw new IllegalArgumentException("Can't calculate matrix product for given input");
            }
            if (n == 0 || p == 0)
                return true;
            for (int i = 0; i < n; i++)
                for (int j = 0; j < p; j++)
                    tasks[i][j] = new CalculateEntry(A, B, i, j).fork();
            for (int i = 0; i < n; i++)
                for (int j = 0; j < p; j++)
                    result[i][j] = tasks[i][j].join();
            return true;
        }
    }
 
    /** This is used to calculate each entry. It won't create more subtasks. */
    private static class CalculateEntry extends ForkJoinTask<Integer> {
        private static final long serialVersionUID = 2781862671220715328L;
        private final int[][] A;
        private final int[][] B;
        private final int i;
        private final int j;
        private Integer result = null;
 
        public CalculateEntry(final int[][] A, final int[][] B, final int i, final int j) {
            this.A = A;
            this.B = B;
            this.i = i;
            this.j = j;
        }
 
        @Override
        public Integer getRawResult() {
            return this.result;
        }
 
        @Override
        protected void setRawResult(final Integer value) {
            this.result = value;
        }
 
        @Override
        protected boolean exec() {
            int sum = 0;
            for (int k = 0; k < B.length; k++) {
                sum += A[i][k] * B[k][j];
            }
            this.setRawResult(sum);
            return true;
        }
    }
 
    public static void main(String[] args) {
        // Note: The matrices would have to be much larger to get better performance than 
        // doing the same without parallel execution. But then the output is hard to read. 
        int[][] A = { { 1, 2, 3 }, { 4, 5, 6 } };
        int[][] B = { { 7, 8 }, { 9, 10 }, { 11, 12 } };
        int[][] result = ForkJoinPool.commonPool().invoke(new MatrixProduct(A, B));
        for (int[] row : result)
            System.out.println(Arrays.toString(row));
    }
}

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎