2017-03-18 106 views
1

我正在嘗試使用Callable(線程池)來實現可以執行矩陣乘法的程序。下面有這個程序。但是,當我在一個線程或8個線程上運行時,我沒有看到執行時間有任何顯着差異。使用線程池的Java矩陣乘法

我花了5個樣本的一個線程和線程8,他們是如下(所有以毫秒爲單位):

1線 - 5433.982472,6872.947063,6371.205237,6079.367443,5842.946494

8線程 - 5260.792683 ,5517.047691,5314.208147,5739.747367,5585.621661

我是新手,我是否做錯了什麼?

package naivematmul; 

import java.util.concurrent.ExecutionException; 
import java.util.concurrent.Executors; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Future; 
import java.util.concurrent.Callable; 

class NaiveMatMul implements Callable<Integer> 
{ 
    private int n; 
    private int a[][]; 
    private int b[][]; 
    private int sum; 
    private int i; 
    private int j; 


    public NaiveMatMul(int n, int a[][], int b[][], int i , int j) 
    { 
      this.n = n; 
      this.a = a; 
      this.b = b; 
      this.i = i; 
      this.j = j; 
      this.sum = sum; 
    } 

    public Integer call() throws Exception 
    { 
     for (int k = 0 ; k < n ; k++) 
     { 
      sum = sum + a[i][k] * b[k][j]; 

     } 
     return sum; 
    } 

    public static void main(String[] args) throws InterruptedException, ExecutionException 
    { 

     int n; 
     int[][] a, b, c; 

     n = 512; 
     a = new int[n][n]; 
     b = new int[n][n]; 
     c = new int[n][n]; 

     int threads = 8; 

     ExecutorService executor = Executors.newFixedThreadPool(threads); 

     for(int i=0; i<n; i++) 
     { 
      for(int j=0; j<n; j++) 
      { 
       a[i][j] = 1; 
      } 
     } 

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

       b[i][j] = 1; 

      } 
     } 


      int sum = 0; 
     long start_time = System.nanoTime(); 
     Future<Integer> future; 

     for (int i = 0; i < n ; i++) 
     { 
      for (int j = 0 ; j < n ; j++) 
      { 
       future = executor.submit(new NaiveMatMul(n, a, b, i, j)); 
       c[i][j] = future.get(); 
       sum = 0; 
      } 

     } 


     long end_time = System.nanoTime(); 
     double difference = (end_time - start_time)/1e6; 
     executor.shutdown(); 




       System.out.println("Time taken : " + difference); 



    } 
} 

回答

0

通過在executor.submit(...)之後調用future.get(),可以防止實際的多線程。您的程序在提交第二個計算之前會等待第一個計算完成。

爲了說明這一點,嘗試用以下取代你的循環:

Future<Integer> futures[][] = new Future[n][n]; 

for (int i = 0; i < n; i++) { 
    for (int j = 0; j < n; j++) { 
     future = executor.submit(new NaiveMatMul(n, a, b, i, j)); 
     futures[i][j] = future; 
    } 
} 

for (int i = 0; i < n; i++) { 
    for (int j = 0; j < n; j++) { 
     c[i][j] = futures[i][j].get(); 
    } 
} 

這是不完全做到這一點的好方法,但你應該看到在你的執行時間的顯著改善。不同之處在於,現在您正在啓動所有線程中的所有計算,然後開始收集結果。

+0

執行時間在3個線程後增加。任何想法爲什麼是這樣?我在超線程的四核i7上運行它,所以它總共有8個線程。另外,我使用的IDE是NetBeans。 –

0

在多個線程中運行程序並不一定意味着更好的性能。在少數情況下,可能會導致性能下降。你必須檢查你的系統上運行的其他進程是什麼?你有多少個CPU核心?

如果你有雙核心處理器,並且你運行8個線程,意味着更多的工作讓java在線程之間進行協調。 爲了獲得最佳性能,請嘗試運行與CPU核心數量相同的線程數,同時在PC /服務器上運行最少的服務。