Java中的多线程矩阵乘法。平均时间缩短了。我是否正确使用执行者?

Java中的多线程矩阵乘法。平均时间缩短了。我是否正确使用执行者?,java,multithreading,matrix-multiplication,executorservice,Java,Multithreading,Matrix Multiplication,Executorservice,我正在尝试进行多线程矩阵乘法,其中比较不同数量的线程的执行时间,从1到100,每次迭代递增10 基本上,我创建了两个100x100矩阵,其单元格中的随机数范围为-10.0到10.0,然后将它们相乘。我将使用不同数量的线程执行25次(每次再增加10次:因此第一次迭代将使用1个线程,第二次迭代将使用10个线程,第三次将使用20个线程等等),然后找到平均完成时间并将该时间存储在一个文件中 我遇到的问题是,我不确定我是否正确使用了执行器。例如,对我来说,这段代码(我还提供了这段代码下面的整个程序代码)表

我正在尝试进行多线程矩阵乘法,其中比较不同数量的线程的执行时间,从1到100,每次迭代递增10

基本上,我创建了两个100x100矩阵,其单元格中的随机数范围为-10.0到10.0,然后将它们相乘。我将使用不同数量的线程执行25次(每次再增加10次:因此第一次迭代将使用1个线程,第二次迭代将使用10个线程,第三次将使用20个线程等等),然后找到平均完成时间并将该时间存储在一个文件中

我遇到的问题是,我不确定我是否正确使用了执行器。例如,对我来说,这段代码(我还提供了这段代码下面的整个程序代码)表示我已经创建了10个线程,在每个线程中,我将使用.execute方法来运行我的LoopTaskA,它恰好是矩阵的乘法。所以我要做的是,在这10个线程之间进行一次乘法。这就是我在这里做的吗?或者我是在10个线程上乘以10倍(即,每个线程一次乘法)

我问这个问题的原因是,当我阅读整个程序时,线程数每增加一次,平均完成时间就会增加。如果我增加了线程的数量,那么完成时间不应该减少吗

根据我发现的另一个问题,也许不是?但我仍然不确定我做错了什么

for(int i = 0; i < 25; i++)
{
    ExecutorService execService = Executors.newFixedThreadPool(10);
    startTime = System.nanoTime();          
    for(int j = 0; j < 10; j++)
    {
        execService.execute(new LoopTaskA(m1,m2));
    }     

import java.util.*;
import java.io.*;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MatrixMultiplication { 
    static double[][] m1 = new double[100][100];
    static double[][] m2 = new double[100][100];

public static void main(String[] args){

    long startTime;
    long endTime;
    long completionTime;
    ArrayList<Long> myTimes = new ArrayList<Long>();
    long addingNumber = 0;
    long averageTime;
    String filepath = "exe_time.csv";

    createMatrix();

    /*This for loop will create 1 thread and then use the execute method from execService
    to multiply the two 100x100 matrices together. The completionTime is how long it takes
    for the whole process to finish. We want to run this thread 25 times and then take the average
    of those completion times*/

    for(int i = 0; i < 25; i++)
    {

    ExecutorService execService = Executors.newFixedThreadPool(1);

    startTime = System.nanoTime(); 

    execService.execute(new LoopTaskA(m1,m2));

    execService.shutdown();

    endTime = System.nanoTime();

    completionTime = (endTime - startTime);

    myTimes.add(completionTime);

    System.out.println("The completion time for one iteration is: " + completionTime);

    }

    /*Takes the completion times that were stored in an arraylist and finds the average*/

    for(int i = 0; i < 25; i++)
    {
        addingNumber = addingNumber + myTimes.remove(0);
    }

    averageTime = (addingNumber / 25);
    System.out.println("The average run time in nanoseconds for 1 thread that ran 25 times is: " + averageTime);
    saveRecord(averageTime, filepath);

    /*We call createMatrix again here so we start with a fresh new matrix*/

    createMatrix();

    /*We are doing the same thing as before but now we have 10 threads and not 1*/

    for(int i = 0; i < 25; i++)
    {

    ExecutorService execService = Executors.newFixedThreadPool(10);

    startTime = System.nanoTime();

        for(int j = 0; j < 10; j++)
        {
            execService.execute(new LoopTaskA(m1,m2));
        } 

    execService.shutdown();

    endTime = System.nanoTime();

    completionTime = (endTime - startTime);

    myTimes.add(completionTime);

    System.out.println("The completion time for one iteration is: " + completionTime);

    }

    for(int i = 0; i < 25; i++)
    {
        addingNumber = addingNumber + myTimes.remove(0);
    }

    averageTime = (addingNumber / 25);
    System.out.println("The average run time in nanoseconds for 10 threads that ran 25 times is: " + averageTime);
    saveRecord(averageTime, filepath);

    createMatrix();

    /*We are doing the same thing as before but now we have 20 threads and not 10*/

    for(int i = 0; i < 25; i++)
    {

    ExecutorService execService = Executors.newFixedThreadPool(20);

    startTime = System.nanoTime();

        for(int j = 0; j < 20; j++)
        {
            execService.execute(new LoopTaskA(m1,m2));
        }

    execService.shutdown();

    endTime = System.nanoTime();

    completionTime = (endTime - startTime);

    myTimes.add(completionTime);

    System.out.println("The completion time for one iteration is: " + completionTime);

    }

    for(int i = 0; i < 25; i++)
    {
        addingNumber = addingNumber + myTimes.remove(0);
    }

    averageTime = (addingNumber / 25);
    System.out.println("The average run time in nanoseconds for 20 threads that ran 25 times is: " + averageTime);
    saveRecord(averageTime, filepath);  

 }

/*Creates the matrix input by taking a random number from the range of
    -10 to 10 and then truncates the number to two decimal places*/

public static double matrixInput(){
    double max = 10.0;
    double min = -10.0;

    Random ran = new Random();
    double random = min + (max - min) * ran.nextDouble();
    double truncatedRan = Math.floor(random*100)/100;
    return truncatedRan;

}

/*Places that random number generated in the matrixInput method into a cell of the matrix.
The goal is to create 2 random 100x100 matrices. The first 100x100 matrix is m1. The second is m2.*/

 public static void createMatrix(){

    for (int row = 0; row < m1.length; row++)
    {
        for (int col = 0; col < m1[0].length; col++)
        {
            m1[row][col] = matrixInput();
        }
    }

    for (int row = 0; row < m2.length; row++)
    {
        for (int col = 0; col < m2[0].length; col++)
        {
            m2[row][col] = matrixInput();
        }
    }

}

/*Method that creates a .csv (comma seperated vector) file which stores 
the average time*/

public static void saveRecord(long averageTime, String filepath)
{
    try
    {
        FileWriter fw = new FileWriter(filepath,true);
        BufferedWriter bw = new BufferedWriter(fw);
        PrintWriter pw = new PrintWriter(bw);

        pw.println(averageTime + ",");
        pw.flush();
        pw.close();

        System.out.println("File has been saved.");
    }   
    catch(Exception E)
    {
        System.out.println("File has NOT been saved.");
    }       
  } 
 }

 import java.util.*;
 public class LoopTaskA implements Runnable{

 double[][] m1;
 double[][] m2;

 @Override
 public void run(){     
    double sum = 0;     
    /*This is to calculate the resulting matrix.We need to know the number or rows of m1 
    and the number of columns in m2 (both of which will be 100 since we want a 100x100 matrix)*/

    double r[][] = new double [100][100];

    /*This multiplies the two 100x100 matrices together. You can think of i here as the row number (which is 100).
    The range of j will depend upon the number of columns in the resultant matrix (range of j = 100)
    The k value will depend upon the number of columns in the first matrix or the number of rows in 
    the second matrix, both of these 100*/
    for(int i = 0; i < 100; i++)
    {

        for(int j = 0; j < 100; j++)
        {
            for(int k = 0; k < 100; k++)
            {
                sum = sum + m1[i][k] * m2[k][j];
            }
            r[i][j] = Math.floor(sum*100)/100;
            sum = 0; //reset to 0 so you can do the calculation for the next value.
        }

    }

    /* for(int i = 0; i < 100; i++)
    {
        for(int j = 0; j < 100; j++)
        {
            System.out.print(r[i][j] + " ");
        }

            System.out.println();
    } */        
 }


 public LoopTaskA(double[][] m1, double[][] m2){
    this.m1 = m1;
    this.m2 = m2;
 }  
}
for(int i=0;i<25;i++)
{
ExecutorService Executors=Executors.newFixedThreadPool(10);
startTime=System.nanoTime();
对于(int j=0;j<10;j++)
{
execService.execute(新的LoopTaskA(m1,m2));
}     
导入java.util.*;
导入java.io.*;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
公共类矩阵乘法{
静态双精度[][]m1=新双精度[100][100];
静态双精度[][]m2=新双精度[100][100];
公共静态void main(字符串[]args){
长启动时间;
长时间;
完成时间长;
ArrayList myTimes=新建ArrayList();
长加法数=0;
平均时间长;
字符串filepath=“exe_time.csv”;
createMatrix();
/*这个for循环将创建1个线程,然后使用execService中的execute方法
将两个100x100矩阵相乘。完成时间是所需的时间
为了完成整个过程,我们要运行这个线程25次,然后取平均值
完成时间是多少*/
对于(int i=0;i<25;i++)
{
ExecutorService Executors=Executors.newFixedThreadPool(1);
startTime=System.nanoTime();
execService.execute(新的LoopTaskA(m1,m2));
execService.shutdown();
endTime=System.nanoTime();
completionTime=(endTime-startTime);
添加(完成时间);
System.out.println(“一次迭代的完成时间为:“+completionTime”);
}
/*获取存储在arraylist中的完成时间并查找平均值*/
对于(int i=0;i<25;i++)
{
addingNumber=addingNumber+myTimes.remove(0);
}
平均时间=(加法数/25);
System.out.println(“运行25次的1个线程的平均运行时间(以纳秒为单位)为:“+averageTime”;
保存记录(平均时间、文件路径);
/*我们在这里再次调用createMatrix,因此我们从一个新的矩阵开始*/
createMatrix();
/*我们正在做与以前相同的事情,但现在我们有10个线程,而不是1个*/
对于(int i=0;i<25;i++)
{
ExecutorService Executors=Executors.newFixedThreadPool(10);
startTime=System.nanoTime();
对于(int j=0;j<10;j++)
{
execService.execute(新的LoopTaskA(m1,m2));
} 
execService.shutdown();
endTime=System.nanoTime();
completionTime=(endTime-startTime);
添加(完成时间);
System.out.println(“一次迭代的完成时间为:“+completionTime”);
}
对于(int i=0;i<25;i++)
{
addingNumber=addingNumber+myTimes.remove(0);
}
平均时间=(加法数/25);
System.out.println(“运行25次的10个线程的平均运行时间(纳秒)为:“+averageTime”);
保存记录(平均时间、文件路径);
createMatrix();
/*我们正在做和以前一样的事情,但是现在我们有20个线程,而不是10个*/
对于(int i=0;i<25;i++)
{
ExecutorService Executors=Executors.newFixedThreadPool(20);
startTime=System.nanoTime();
对于(int j=0;j<20;j++)
{
execService.execute(新的LoopTaskA(m1,m2));
}
execService.shutdown();
endTime=System.nanoTime();
completionTime=(endTime-startTime);
添加(完成时间);
System.out.println(“一次迭代的完成时间为:“+completionTime”);
}
对于(int i=0;i<25;i++)
{
addingNumber=addingNumber+myTimes.remove(0);
}
平均时间=(加法数/25);
System.out.println(“运行25次的20个线程的平均运行时间(纳秒)为:“+averageTime”);
保存记录(平均时间、文件路径);
}
/*通过从范围中选取一个随机数来创建矩阵输入
-10到10,然后将数字截断到小数点后两位*/
公共静态双矩阵put(){
双倍最大值=10.0;
双分钟=-10.0;
Random ran=新的Random();
double random=min+(max-min)*ran.nextDouble();
双截断面=数学楼层(随机*100)/100;
返回截断面;
}
/*将matrixInput方法中生成的随机数放入矩阵的单元格中。
目标是创建2个随机100x100矩阵。第一个100x100矩阵是m1。第二个是m2*/
公共静态void createMatrix(){