简体   繁体   中英

How can I implement 2D Square Matrix multiplication using multi-threading in Java?

I want to multiply two square 2D matrix using multi-threading features in Java in order to save time.

What is the best way to do this? My first priority is to save time.

Please look at the code that I wrote. The solution I am looking is that it will do what my code do but only difference is execution time.

Multi-Threading should save time right?

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

public class ExtraTaskOS {

    // Generatining Random Number Method
    static int generateRandomNumber() {

        int number = (int) (Math.random() * (9 - 1)) + 1;
        return number;
    }

    public static void main(String[] args) throws IOException {

        // Store current time
        long startTime = System.nanoTime();

        Scanner sc = new Scanner(System.in);

        System.out.print("Enter number of Eelement for both Square Matrix: ");
        int n = sc.nextInt();


        // Generaing First Matrix
        int[][] matrix01 = new int[n][n];

        for (int i = 0; i < matrix01.length; i++) {
            for (int j = 0; j < matrix01.length; j++) {
                matrix01[i][j] = generateRandomNumber();
            }
        }

        // Writing Matrix01 to Text File
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < matrix01.length; i++)//for each row
        {
            for (int j = 0; j < matrix01.length; j++)//for each column
            {
                builder.append(matrix01[i][j] + "");//append to the output string
                if (j < matrix01.length - 1)//if this is not the last row element
                {
                    builder.append(",");//then add comma (if you don't like commas you can use spaces)
                }
            }
            builder.append("\n");//append new line at the end of the row
        }
        BufferedWriter writer = new BufferedWriter(new FileWriter("matrix01.txt"));
        writer.write(builder.toString());//save the string representation of the board
        writer.close();

        // Generating Second Matix
        int[][] matrix02 = new int[n][n];

        for (int i = 0; i < matrix02.length; i++) {
            for (int j = 0; j < matrix02.length; j++) {
                matrix02[i][j] = generateRandomNumber();
            }
        }

        // Writing Matrix02 to Text File
        StringBuilder builder2 = new StringBuilder();

        for (int i = 0; i < matrix02.length; i++)//for each row
        {
            for (int j = 0; j < matrix02.length; j++)//for each column
            {
                builder2.append(matrix02[i][j] + "");//append to the output string
                if (j < matrix02.length - 1)//if this is not the last row element
                {
                    builder2.append(",");//then add comma (if you don't like commas you can use spaces)
                }
            }
            builder2.append("\n");//append new line at the end of the row
        }
        BufferedWriter writer2 = new BufferedWriter(new FileWriter("matrix02.txt"));
        writer2.write(builder2.toString());//save the string representation of the board
        writer2.close();

        // Printing both 2D Arrays
        for (int[] arr : matrix01) {
            System.out.println(Arrays.toString(arr));
        }
        System.out.println("");
        for (int[] arr : matrix02) {
            System.out.println(Arrays.toString(arr));
        }

        // Multiplying both matrix
        int[][] productTwoMatrix = new int[n][n];

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {

              for(int k=0; k<n; k++){
                productTwoMatrix[i][j] += matrix01[i][k] * matrix02[k][j];

              }  

            }
        }

        // Printing Result
        System.out.println("\nResult: ");
        for (int[] arr : productTwoMatrix) {
            System.out.println(Arrays.toString(arr));
        }

        // Calculate Execution time
        long endTime = System.nanoTime();
        long totalTime = endTime - startTime;
        long timeInMiliSecond = (totalTime / 1_000_000);
        System.out.println("Execution Time: "+ timeInMiliSecond + " miliseconds");


    }

}

The new code using multi-threading should save time.

First: learn how to properly measure your code. You do

// Store current time
long startTime = System.nanoTime();

even before you ask the user for his input. Then you do file IO and print various things to System.out. Hint: each of those actions will probably take hundreds of milliseconds, waiting for a human to enter a number ... could take hours. Thus: only measure the part that really matters to you (that would be the multiplication part). Avoid all kinds of IO operation while measuring, too!

You see, hundred milliseconds, that doesn't sound much, but when you do correct measurements, you will find that your CPU can do a ton of things in 100 ms (if you don't disturb it all the time with IO work).

Regarding multiple threads, you are also going down the wrong rabbit hole:

I want to multiply two square 2D matrix using multi-threading features in Java in order to save time.

That is (almost) non-sensical. You see, CPU intensive workloads do not profit from using multiple threads. In the end, the CPU needs to turn to memory, fetch values, do a few computations, and write back values to memory. Doing that in parallel isn't necessarily making things go faster. To the contrary, you first have to "pay" various penalty fees:

  • Creating a thread isn't a cheap operation. You must for sure process thousands of elements before alone the price tag for new Thread() has been made up for.
  • When we talk huge arrays (and as said: small arrays will definitely give you worse results when using more than one thread) ... then it matters quite a bit in which order data is requested from memory. You know, CPUs have caches. A cache miss can be extremely expensive. And guess what happens when you have multiple threads accessing different parts of your matrixes? Exactly: you will most likely cause that: cache misses.

In case I didn't discourage you, and you actually do this for learning purposes, the answer is quite simple. Matrix multiplication works by fetching the values of one row, and the values from a column of the other matrix, you multiple and sum up the results.

Now: instead of having one thread going in three loops to do these things, you could for example have one thread compute the first row of the result matrix, the second thread computes the second row, and so on.

The nice thing here: you can simply "slice" the data that needs to be processed. No result value depends on other results, so there is no need for synchronisation at all. You can use 1 thread, 2, 4, n, almost as many you want to.

What I would suggest:

  • don't ask the user for any input. Simply generate matrixes of a fixed size, maybe 100x100, 1000x1000, 10000x10000.
  • maybe seed your random number generator, so that all multiplications operate on the exact same data. - don't print the whole array in the end (because as said: use large arrays). An array that fits on your screen is too small to give you any meaningful measurements. But sum up the final matrix for example (to avoid that the JIT optimizes away the whole operation: you have to make sure that some result of your operation is used somehow)
  • try to write code that allows you to quickly change the number of threads, without changing anything else. So that you can multiple using 1, 2, 4, 8, 16 threads.

And when you are done with using raw, "bare metal" threads, copy your code, remove all the thread stuff, and try implementing matrix multiplication using an ExecutorService . When that works, go one step further and look at Futures and think how those could be used here.

As said: you shouldn't be doing this for performance. The only good reason for you to write such code is to learn how to do it (right).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM