使矩阵乘法并行工作 java
Making a matrix multiplication work in parallel java
我根据所学创建矩阵乘法的知识创建了这段代码。
但我想并行处理这段代码,以便它可以在多个线程上运行。
有人可以 help/do 这个给我吗?我不太确定该怎么做!
已更新:
public class ParallelMatrix {
public final static int N = 1000; //Random size of matrix
public static void main(String[] args) throws InterruptedException {
long startTime = System.currentTimeMillis();
//Create and multiply matrix of random size N.
double[][] a = new double[N][N];
double[][] b = new double[N][N];
double[][] c = new double[N][N];
int i, j, k;
for (i = 0; i < N; i++)
for (j = 0; j < N; j++) {
a[i][j] = i + j;
b[i][j] = i * j;
}
ExecutorService pool = Executors.newFixedThreadPool(10);
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
pool.submit(new Multi(N, i, j, a, b, c));
}
}
pool.shutdown();
pool.awaitTermination(1, TimeUnit.DAYS);
long endTime = System.currentTimeMillis();
System.out.println("Calculation completed in " +
(endTime - startTime) + " milliseconds");
}
static class Multi implements Runnable {
final int N;
final double[][] a;
final double[][] b;
final double[][] c;
final int i;
final int j;
public Multi(int N, int i, int j, double[][] a, double[][] b, double[][] c) {
this.N = N;
this.i = i;
this.j = j;
this.a = a;
this.b = b;
this.c = c;
}
@Override
public void run() {
for (int k = 0; k < N; k++) c[i][j] += a[i][k] * b[k][j];
}
}
}
您可以在单独的线程中计算矩阵 C 的每个单元格,例如:
class Multi implements Runnable {
final int N;
final double[][] a;
final double[][] b;
final double[][] c;
final int i;
final int j;
...
@Override
public void run() {
for (int k = 0; k < N; k++)
c[i][j] += a[i][k] * b[k][j];
}
}
ExecutorService pool = ...;
for (int i = 0;...)
for (int j = 0;...)
pool.submit(new Multi(N, i, j, a, b, c));
pool.shutdown();
pool.awaitTermination(1, TimeUnit.DAYS);
虽然对整列或整行执行此操作更有意义。
FWIW 这里是使用 Java 流 API 的替代方法。可能有更好的方法来实现并行矩阵乘法,尤其是使用 BLAS 库和 GPU 实现(如 jcuBLAS)。但是如果你需要香草 Java 那么这将是一个选项。
static double[][] multiplyStreams(double[][] a, double[][] b) {
assert a.length == b.length;
assert a.length > 0;
assert a[0].length == b[0].length;
assert a.length == a[0].length; // just work on square matrices
int N = a.length;
double[][] result = new double[N][N];
IntStream.range(0, N).parallel().forEach(i ->
IntStream.range(0, N).parallel().forEach(j ->
IntStream.range(0, N).forEach(k ->
result[i][j] += a[i][k] * b[k][j]
)
)
);
return result;
}
注意:比较@Ali Mohammad 的原始方法和 Streams 版本,Streams 版本在我的机器上稍微快一些:
Calculation completed in 1187 milliseconds
Streams calculation completed in 963 milliseconds
比较代码:
startTime = System.currentTimeMillis();
double[][] d = multiplyStreams(a, b);
endTime = System.currentTimeMillis();
System.out.println("Streams calculation completed in " +
(endTime - startTime) + " milliseconds");
您还可以扩展代码,使其适用于任何 [M x K][K x N] 矩阵乘法。
我根据所学创建矩阵乘法的知识创建了这段代码。
但我想并行处理这段代码,以便它可以在多个线程上运行。
有人可以 help/do 这个给我吗?我不太确定该怎么做!
已更新:
public class ParallelMatrix {
public final static int N = 1000; //Random size of matrix
public static void main(String[] args) throws InterruptedException {
long startTime = System.currentTimeMillis();
//Create and multiply matrix of random size N.
double[][] a = new double[N][N];
double[][] b = new double[N][N];
double[][] c = new double[N][N];
int i, j, k;
for (i = 0; i < N; i++)
for (j = 0; j < N; j++) {
a[i][j] = i + j;
b[i][j] = i * j;
}
ExecutorService pool = Executors.newFixedThreadPool(10);
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
pool.submit(new Multi(N, i, j, a, b, c));
}
}
pool.shutdown();
pool.awaitTermination(1, TimeUnit.DAYS);
long endTime = System.currentTimeMillis();
System.out.println("Calculation completed in " +
(endTime - startTime) + " milliseconds");
}
static class Multi implements Runnable {
final int N;
final double[][] a;
final double[][] b;
final double[][] c;
final int i;
final int j;
public Multi(int N, int i, int j, double[][] a, double[][] b, double[][] c) {
this.N = N;
this.i = i;
this.j = j;
this.a = a;
this.b = b;
this.c = c;
}
@Override
public void run() {
for (int k = 0; k < N; k++) c[i][j] += a[i][k] * b[k][j];
}
}
}
您可以在单独的线程中计算矩阵 C 的每个单元格,例如:
class Multi implements Runnable {
final int N;
final double[][] a;
final double[][] b;
final double[][] c;
final int i;
final int j;
...
@Override
public void run() {
for (int k = 0; k < N; k++)
c[i][j] += a[i][k] * b[k][j];
}
}
ExecutorService pool = ...;
for (int i = 0;...)
for (int j = 0;...)
pool.submit(new Multi(N, i, j, a, b, c));
pool.shutdown();
pool.awaitTermination(1, TimeUnit.DAYS);
虽然对整列或整行执行此操作更有意义。
FWIW 这里是使用 Java 流 API 的替代方法。可能有更好的方法来实现并行矩阵乘法,尤其是使用 BLAS 库和 GPU 实现(如 jcuBLAS)。但是如果你需要香草 Java 那么这将是一个选项。
static double[][] multiplyStreams(double[][] a, double[][] b) {
assert a.length == b.length;
assert a.length > 0;
assert a[0].length == b[0].length;
assert a.length == a[0].length; // just work on square matrices
int N = a.length;
double[][] result = new double[N][N];
IntStream.range(0, N).parallel().forEach(i ->
IntStream.range(0, N).parallel().forEach(j ->
IntStream.range(0, N).forEach(k ->
result[i][j] += a[i][k] * b[k][j]
)
)
);
return result;
}
注意:比较@Ali Mohammad 的原始方法和 Streams 版本,Streams 版本在我的机器上稍微快一些:
Calculation completed in 1187 milliseconds
Streams calculation completed in 963 milliseconds
比较代码:
startTime = System.currentTimeMillis();
double[][] d = multiplyStreams(a, b);
endTime = System.currentTimeMillis();
System.out.println("Streams calculation completed in " +
(endTime - startTime) + " milliseconds");
您还可以扩展代码,使其适用于任何 [M x K][K x N] 矩阵乘法。