带有线程的矩阵乘法Java

问题描述 投票:5回答:7

我正在尝试创建一个带有线程用于矩阵乘法的Java程序。这是源代码:

import java.util.Random;

public class MatrixTest {

//Creating the matrix
static int[][] mat = new int[3][3];
static int[][] mat2 = new int[3][3];
static int[][] result = new int[3][3];

public static void main(String [] args){

    //Creating the object of random class
    Random rand = new Random();


    //Filling first matrix with random values
    for (int i = 0; i < mat.length; i++) {
        for (int j = 0; j < mat[i].length; j++) {
            mat[i][j]=rand.nextInt(10);
        }
    }

    //Filling second matrix with random values
    for (int i = 0; i < mat2.length; i++) {
        for (int j = 0; j < mat2[i].length; j++) {
            mat2[i][j]=rand.nextInt(10);
        }
    }

    try{
        //Object of multiply Class
        Multiply multiply = new Multiply(3,3);

        //Threads
        MatrixMultiplier thread1 = new MatrixMultiplier(multiply);
        MatrixMultiplier thread2 = new MatrixMultiplier(multiply);
        MatrixMultiplier thread3 = new MatrixMultiplier(multiply);

        //Implementing threads
        Thread th1 = new Thread(thread1);
        Thread th2 = new Thread(thread2);
        Thread th3 = new Thread(thread3);

        //Starting threads
        th1.start();
        th2.start();
        th3.start();

        th1.join();
        th2.join();
        th3.join();

    }catch (Exception e) {
        e.printStackTrace();
    }

    //Printing the result
    System.out.println("\n\nResult:");
    for (int i = 0; i < result.length; i++) {
        for (int j = 0; j < result[i].length; j++) {
            System.out.print(result[i][j]+" ");
        }
        System.out.println();
    }
  }//End main

  }//End Class

   //Multiply Class
   class Multiply extends MatrixTest {

private int i;
private int j;
private int chance;

public Multiply(int i, int j){
    this.i=i;
    this.j=j;
    chance=0;
}

//Matrix Multiplication Function
public synchronized void multiplyMatrix(){

    int sum=0;
    int a=0;
    for(a=0;a<i;a++){
        sum=0;
        for(int b=0;b<j;b++){
            sum=sum+mat[chance][b]*mat2[b][a];
        }
        result[chance][a]=sum;
    }

    if(chance>=i)
        return;
    chance++;
}
}//End multiply class

//Thread Class
     class MatrixMultiplier implements Runnable {

private final Multiply mul;

public MatrixMultiplier(Multiply mul){
    this.mul=mul;
}

@Override
public void run() {
    mul.multiplyMatrix();
}
}

我刚刚在Eclipse上尝试过,并且可以工作,但是现在我想创建该程序的另一个版本,在该版本中,我将对结果矩阵上的每个单元格使用一个线程。例如,我有两个3x3矩阵。因此,结果矩阵将为3x3。然后,我想使用9个线程来计算结果矩阵的9个单元格中的每一个。

有人可以帮我吗?

最佳问候

java multithreading matrix concurrency matrix-multiplication
7个回答
2
投票

您可以按以下方式创建n线程(注意:numberOfThreads是要创建的线程数。这是单元格的数目):

List<Thread> threads = new ArrayList<>(numberOfThreads);

for (int x = 0; x < numberOfThreads; x++) {
   Thread t = new Thread(new MatrixMultiplier(multiply));
   t.start();
   threads.add(t);
}

for (Thread t : threads) {
   t.join();
}

2
投票

使用此代码,我认为我可以解决我的问题。我没有在方法中使用同步,但是我认为在这种情况下没有必要。

import java.util.Scanner;

class MatrixProduct extends Thread {
      private int[][] A;
      private int[][] B;
      private int[][] C;
      private int rig,col;
      private int dim;

      public MatrixProduct(int[][] A,int[][] B,int[][] C,int rig, int col,int dim_com)
      {
         this.A=A;    
         this.B=B;
         this.C=C;
         this.rig=rig;    
         this.col=col; 
         this.dim=dim_com;     
      }

     public void run()
     {
         for(int i=0;i<dim;i++){
               C[rig][col]+=A[rig][i]*B[i][col];        
         }      
          System.out.println("Thread "+rig+","+col+" complete.");        
     }          
 }

 public class MatrixMultiplication {
       public static void main(String[] args)
      {      
          Scanner In=new    Scanner(System.in); 

          System.out.print("Row of Matrix A: ");     
          int rA=In.nextInt();
          System.out.print("Column of Matrix A: ");
          int cA=In.nextInt();
          System.out.print("Row of Matrix B: ");     
          int rB=In.nextInt();
          System.out.print("Column of Matrix B: ");
          int cB=In.nextInt();
          System.out.println();

          if(cA!=rB)
          {
               System.out.println("We can't do the matrix product!");
               System.exit(-1);
          }
         System.out.println("The matrix result from product will be "+rA+" x "+cB);
       System.out.println();
       int[][] A=new int[rA][cA];
       int[][] B=new int[rB][cB];
       int[][] C=new int[rA][cB];
       MatrixProduct[][] thrd= new MatrixProduct[rA][cB];

       System.out.println("Insert A:");
       System.out.println();
        for(int i=0;i<rA;i++)
         {
          for(int j=0;j<cA;j++)
          {
              System.out.print(i+","+j+" = ");
              A[i][j]=In.nextInt();
          }
         }        
         System.out.println();    
         System.out.println("Insert B:");
         System.out.println();
          for(int i=0;i<rB;i++)
          {
           for(int j=0;j<cB;j++)
            {
            System.out.print(i+","+j+" = ");
            B[i][j]=In.nextInt();
            }        
          }
          System.out.println();

        for(int i=0;i<rA;i++)
        {
         for(int j=0;j<cB;j++)
          {
            thrd[i][j]=new MatrixProduct(A,B,C,i,j,cA);
            thrd[i][j].start();
          }
        }

        for(int i=0;i<rA;i++)
        {
            for(int j=0;j<cB;j++)
            {
                try{
                    thrd[i][j].join();
                }
            catch(InterruptedException e){}
            }
        }        

        System.out.println();
        System.out.println("Result");
        System.out.println();
        for(int i=0;i<rA;i++)
        {
            for(int j=0;j<cB;j++)
            {
                System.out.print(C[i][j]+" ");
            }    
            System.out.println();            
        }       
}      
}

1
投票

请使用新的执行程序framework创建线程,而不要手动执行管道。

 ExecutorService executor = Executors.newFixedThreadPool(numberOfThreadsInPool);
    for (int i = 0; i < numberOfThreads; i++) {
        Runnable worker = new Thread(new MatrixMultiplier(multiply));;
        executor.execute(worker);
    }
    executor.shutdown();
    while (!executor.isTerminated()) {
    }

0
投票

简单来说,您要做的就是,

1)创建n个(结果矩阵中没有单元格)线程。分配他们的角色。 (例如:考虑M X N,其中M和N是矩阵。“ thread1”负责将M的row_1元素与N的column_1元素相乘并存储结果。这是所得矩阵的cell_1的值。)

2)启动每个线程的进程。 (通过start()方法)

3)等待所有线程完成其进程并存储每个单元的结果值。因为这些过程应该在显示结果矩阵之前完成。 (您也可以通过join()方法执行此操作,也可以使用其他方法)

4)现在,您可以显示结果矩阵。

注意:

1]由于在此示例中,共享资源(M和N)仅用于只读目的,因此您不需要使用“同步”方法来访问它们。

2)您可以看到,在此程序中,有一组线程正在运行,并且所有这些线程都需要自行完成特定状态,然后才能继续执行整个程序的下一步。这种多线程编程模型称为Barrier


0
投票

在我的解决方案中,我为每个工作人员分配的行数numRowForThread等于:(matA的行数)/(线程的数)。

public class MatMulConcur {

private final static int NUM_OF_THREAD =1 ;
private static Mat matC;

public static Mat matmul(Mat matA, Mat matB) {
    matC = new Mat(matA.getNRows(),matB.getNColumns());
    return mul(matA,matB);
}

private static Mat mul(Mat matA,Mat matB) {

    int numRowForThread;
    int numRowA = matA.getNRows();
    int startRow = 0;

    Worker[] myWorker = new Worker[NUM_OF_THREAD];

    for (int j = 0; j < NUM_OF_THREAD; j++) {
        if (j<NUM_OF_THREAD-1){
            numRowForThread = (numRowA / NUM_OF_THREAD);
        } else {
            numRowForThread = (numRowA / NUM_OF_THREAD) + (numRowA % NUM_OF_THREAD);
        }
        myWorker[j] = new Worker(startRow, startRow+numRowForThread,matA,matB);
        myWorker[j].start();
        startRow += numRowForThread;
    }

    for (Worker worker : myWorker) {
        try {
            worker.join();
        } catch (InterruptedException e) {

        }
    }
    return matC;
}

private static class Worker extends Thread {

    private int startRow, stopRow;
    private Mat matA, matB;

    public Worker(int startRow, int stopRow, Mat matA, Mat matB) {
        super();
        this.startRow = startRow;
        this.stopRow = stopRow;
        this.matA = matA;
        this.matB = matB;
    }

    @Override
    public void run() {
        for (int i = startRow; i < stopRow; i++) {
            for (int j = 0; j < matB.getNColumns(); j++) {
                double sum = 0;
                for (int k = 0; k < matA.getNColumns(); k++) {
                    sum += matA.get(i, k) * matB.get(k, j);
                }
                matC.set(i, j, sum);
            }
        }
    }
}

class Mat的位置,我使用了此实现:

public class Mat {

   private double[][] mat;

   public Mat(int n, int m) {
      mat = new double[n][m];
   }

   public void set(int i, int j, double v) {
      mat[i][j] = v;
   }

   public double get(int i, int j) {
      return mat[i][j];
   }

   public int getNRows() {
      return mat.length;
   }

   public int getNColumns() {
      return mat[0].length;
   }
}

0
投票

根据每个单元格的线程,在Eclipse中尝试了以下代码。它工作正常,您可以检查一下。

class ResMatrix{

    static int[][] arrres = new int[2][2];
}

class Matrix{

    int [][] arr = new int[2][2];

    void setV(int v) {
        //int tmp = v;
        for(int i=0;i<2;i++) {
            for(int j=0;j<2;j++) {
                arr[i][j] = v;
                v = v + 1;
            }
        }
    }
    int [][] getV(){
        return arr;
    }
}

class Mul extends Thread {
    public int row;
    public int col;
    Matrix m;
    Matrix m1;

    Mul(int row,int col,Matrix m,Matrix m1){
        this.row = row;
        this.col = col;
        this.m = m;
        this.m1 = m1;
    }

    public void run() {
        //System.out.println("Started Thread: "+Thread.currentThread().getName());
        int tmp=0;
        for(int i=0;i<2;i++) {
            tmp = tmp + this.m.getV()[row][i] * this.m1.getV()[i][col];
        }
        ResMatrix.arrres[row][col] = tmp;
        System.out.println("Started Thread END: "+Thread.currentThread().getName());
    }

}



public class Test {

    //static int[][] arrres =new int[2][2];
    public static void main(String[]args) throws InterruptedException {

        Matrix mm = new Matrix();
        mm.setV(1);
        Matrix mm1 = new Matrix();
        mm1.setV(2);

        for(int i=0;i<2;i++) {
            for(int j=0;j<2;j++) {
                Mul mul = new Mul(i,j,mm,mm1);
                mul.start();
            //  mul.join();
            }
        }

        for(int i=0;i<2;i++) {
            for(int j=0;j<2;j++) {
                System.out.println("VALUE: "+ResMatrix.arrres[i][j]);
            }
        }


    }

}

0
投票

如下所述考虑Matrix.java和Main.java。

public class Matrix extends Thread {
private static int[][] a;
private static int[][] b;
private static int[][] c;

/* You might need other variables as well */
private int i;
private int j;
private int z1;

private int s;
private int k;

public Matrix(int[][] A, final int[][] B, final int[][] C, int i, int j, int z1) { // need to change this, might
                                                                                    // need some information
    a = A;
    b = B;
    c = C;
    this.i = i;
    this.j = j;
    this.z1 = z1; // a[0].length
}

public void run() {
    synchronized (c) {
        // 3. How to allocate work for each thread (recall it is the run function which
        // all the threads execute)

        // Here this code implements the allocated work for perticular thread
        // Each element of the resulting matrix will generate by a perticular thread
        for (s = 0, k = 0; k < z1; k++)
            s += a[i][k] * b[k][j];
        c[i][j] = s;

    }

}

public static int[][] returnC() {
    return c;
}

public static int[][] multiply(final int[][] a, final int[][] b) {

    /*
     * check if multipication can be done, if not return null allocate required
     * memory return a * b
     */

    final int x = a.length;
    final int y = b[0].length;

    final int z1 = a[0].length;
    final int z2 = b.length;

    if (z1 != z2) {
        System.out.println("Cannnot multiply");
        return null;
    }

    final int[][] c = new int[x][y];
    int i, j;

    // 1. How to use threads to parallelize the operation?
    // Every element in the resulting matrix will be determined by a different
    // thread

    // 2. How may threads to use?
    // x * y threads are used to generate the result.
    for (i = 0; i < x; i++)
        for (j = 0; j < y; j++) {
            try {
                Matrix temp_thread = new Matrix(a, b, c, i, j, z1);
                temp_thread.start();

                // 4. How to synchronize?

                // synchronized() is used with join() to guarantee that the perticular thread
                // will be accessed first

                temp_thread.join();

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    return Matrix.returnC();
}

}

您可以使用Main.java给出2个需要相乘的矩阵。

class Main { 
public static int [][] a = {{1, 1, 1},
            {1, 1, 1},
            {1, 1, 1}};

public static int [][] b = {{1 },
            {1 },
            {1 }};


public static void print_matrix(int [][] a) {
for(int i=0; i < a.length; i++) {
    for(int j=0; j< a[i].length; j++) 
    System.out.print(a[i][j] + " "); 
    System.out.println();
}
}


public static void main(String [] args) { 

int [][] x = Matrix.multiply(a, b); 
print_matrix(x); // see if the multipication is correct     

}

}

© www.soinside.com 2019 - 2024. All rights reserved.