2017-03-18 38 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 /服务器上运行最少的服务。