矩阵乘法与线程 Java
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32371662/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Matrix Multiplication with threads Java
提问by WhatElse88
I'm trying to create a Java program with threads for matrix multiplication. This is the source code:
我正在尝试创建一个带有用于矩阵乘法的线程的 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();
}
}
I just tried on Eclipse and it works, but now I want to create another version of that program in which, I use one thread for each cell that I'll have on the result matrix. For example I've got two 3x3 matrices. So the result matrix will be 3x3. Then, I want to use 9 threads to calculate each one of the 9 cells of the result matrix.
我刚刚尝试过 Eclipse 并且它可以工作,但是现在我想创建该程序的另一个版本,在该版本中,我为结果矩阵上的每个单元格使用一个线程。例如,我有两个 3x3 矩阵。所以结果矩阵将是 3x3。然后,我想使用 9 个线程来计算结果矩阵的 9 个单元格中的每一个。
Can anyone help me?
谁能帮我?
Best Regards
最好的祝福
回答by Nicholas Robinson
You can create n
Threads as follows (Note: numberOfThreads
is the number of threads that you want to create. This will be the number of cells):
您可以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();
}
回答by WhatElse88
With this code i think that i resolve my problem. I don't use synchronized in the methods but i think that is not necessary in that case.
有了这段代码,我认为我解决了我的问题。我不在方法中使用同步,但我认为在这种情况下没有必要。
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();
}
}
}
回答by RobAu
Please use the new Executor frameworkto create Threads, instead of manually doing the plumbing.
请使用新的 Executor框架来创建线程,而不是手动进行管道操作。
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()) {
}
回答by Supun Wijerathne
In simple terms, what you all need to do is,
简单来说,你们需要做的就是,
1) Create n (no of cells in resultant matrix) threads. Assign their roles. (Ex: Consider M X N, where M and N are matrices. 'thread1' is responsible for the multiplication of M's row_1 elements with N's column_1 elements and storing the result. This is the value for the resultant matrix's cell_1.)
1) 创建 n 个(结果矩阵中没有单元格)线程。分配他们的角色。(例如:考虑 MXN,其中 M 和 N 是矩阵。'thread1' 负责将 M 的 row_1 元素与 N 的 column_1 元素相乘并存储结果。这是结果矩阵的 cell_1 的值。)
2) Start each thread's process. (by start() method)
2) 启动每个线程的进程。(通过 start() 方法)
3) Wait until all the threads finish their processes and store the resultant value of each cell. Because those processes should be finished before displaying the resultant matrix. (You can do this by join() methods, and other possibilities too)
3) 等待所有线程完成其进程并存储每个单元格的结果值。因为这些过程应该在显示结果矩阵之前完成。(您可以通过 join() 方法以及其他可能性来做到这一点)
4) Now, you can display the resultant matrix.
4) 现在,您可以显示结果矩阵。
Note:
笔记:
1) Since, in this example, the shared resources (M and N) are only used to read only purpose, you don't need to use 'synchronized' methods to access them.
1) 由于在本例中,共享资源(M 和 N)仅用于只读目的,因此您无需使用“同步”方法来访问它们。
2) You can see, in this program, there are a group of threads running and all of them needs to achieve a specific status by their own, before continuing the next step of the whole program. This multi-threaded programming model is known as a Barrier.
2)可以看到,在这个程序中,有一组线程在运行,它们都需要自己达到一个特定的状态,才能继续整个程序的下一步。这种多线程编程模型称为Barrier。
回答by Massimiliano Giunchi
In my solution I assigned to each worker a number of rows numRowForThread
equals to: (number of rows of matA)/(number of threads).
在我的解决方案中,我分配给每个工人的行数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);
}
}
}
}
where for the class Mat
, I used this implementation:
对于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;
}
}
回答by gopal pawar
Tried below code in eclipse as per thread for each cell. It works fine, you can check it.
根据每个单元的线程在 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]);
}
}
}
}