簡體   English   中英

如何在Java中使用多線程實現2D方陣乘法?

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

我想使用Java中的多線程功能將兩個正方形2D矩陣相乘,以節省時間。

做這個的最好方式是什么? 我的首要任務是節省時間。

請查看我編寫的代碼。 我正在尋找的解決方案是它將執行我的代碼所執行的操作,但唯一的區別是執行時間。

多線程應該節省時間對嗎?

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");


    }

}

使用多線程的新代碼應節省時間。

首先:學習如何正確評估代碼。 你做

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

甚至您要求用戶輸入之前。 然后,您進行文件IO並將各種內容打印到System.out。 提示:這些動作中的每一個動作可能要花費數百毫秒,等待人類輸入數字……可能要花費數小時。 因此: 測量對您真正重要的部分(即乘法部分)。 測量時也要避免各種IO操作!

您會看到幾百毫秒,這聽起來並不多,但是當您進行正確的測量時,您會發現您的CPU可以在100毫秒內完成很多工作(如果您不會一直在進行IO工作時打擾它) 。

關於多線程,您還會遇到錯誤的兔子漏洞:

我想使用Java中的多線程功能將兩個正方形2D矩陣相乘,以節省時間。

那(幾乎)是荒謬的。 您會看到,占用大量CPU的工作負載無法從使用多個線程中獲利。 最后,CPU需要轉向內存,獲取值,進行一些計算,然后將值寫回內存。 並行執行此操作不一定會使處理速度更快。 相反,您首先必須“支付”各種罰款:

  • 創建線程不是一個便宜的操作。 在確定new Thread()的價格標簽之前,您必須確保處理成千上萬個元素。
  • 當我們討論大型數組時(如前所述:使用多個線程時,小型數組肯定會給您帶來更糟糕的結果)...那么從內存中請求順序數據就相當重要了。 您知道,CPU有緩存。 高速緩存未命中可能非常昂貴。 猜猜當您有多個線程訪問矩陣的不同部分時會發生什么? 確實:您很可能會導致以下原因:緩存未命中。

萬一我不勸阻您,而您實際上是出於學習目的而這樣做,答案很簡單。 矩陣乘法的工作原理是:獲取一行的值,並從另一矩陣的一列中獲取值,然后對它們進行乘法運算並求和。

現在:您可以讓一個線程計算結果矩陣的第一行,而第二個線程計算第二行,以此類推,而不是讓一個線程進入三個循環來執行這些操作。

這里的好處是:您可以簡單地“切片”需要處理的數據。 沒有結果值取決於其他結果,因此完全不需要同步。 您可以使用1個線程,2、4,n,幾乎可以使用任意數量的線程。

我的建議是:

  • 不要要求用戶輸入任何內容。 只需生成固定大小(例如100x100、1000x1000、10000x10000)的矩陣即可。
  • 可能會為您的隨機數生成器播種,以便所有乘法都對完全相同的數據進行運算。 -不要最后打印整個數組(因為如前所述:使用大數組)。 屏幕上適合的陣列太小,無法進行有意義的測量。 但是,例如, 總結一下最終矩陣(為避免JIT優化整個操作:您必須確保以某種方式使用了某些操作結果)
  • 嘗試編寫允許您快速更改線程數而不更改任何其他內容的代碼。 這樣就可以使用1、2、4、8、16個線程進行多重處理。

使用完原始的“裸機”線程后,復制代碼,刪除所有線程內容,然后嘗試使用ExecutorService實現矩陣乘法。 當這種方法可行時,請進一步研究一下期貨,並思考如何在這里使用這些期貨

如前所述:您不應該這樣做來提高性能。 您編寫此類代碼的唯一好理由是學習如何做(正確)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM