Java 使用线程池的矩阵乘法
Java Matrix Multiplication using Thread Pool
我正在尝试实现一个可以使用 Callable(线程池)进行矩阵乘法的程序。我在下面有这个程序。但是,当我 运行 在一个线程或 8 个线程上执行时,我没有看到执行时间有任何显着差异。
我为一个线程和8个线程取了5个样本,它们如下(均以毫秒为单位):
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);
}
}
运行 多线程中的程序并不一定意味着更好的性能。在少数情况下,它会导致性能下降。您必须检查系统上的所有其他进程 运行ning 是什么?你有多少 CPU 个内核?
如果您有双核处理器并且 运行 8 个线程意味着 java 需要更多工作来协调线程之间的关系。
为获得最佳性能,请尝试 运行在您的 PC/server.
上使用与 CPU 核心数量相同的线程数,并在您的 PC/server 上使用最少的服务 运行ning
通过在 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();
}
}
这并不是一个很好的方法,但您应该会看到执行时间的显着改善。不同之处在于,现在您正在启动所有线程中的所有计算,然后开始收集结果。
我正在尝试实现一个可以使用 Callable(线程池)进行矩阵乘法的程序。我在下面有这个程序。但是,当我 运行 在一个线程或 8 个线程上执行时,我没有看到执行时间有任何显着差异。
我为一个线程和8个线程取了5个样本,它们如下(均以毫秒为单位):
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);
}
}
运行 多线程中的程序并不一定意味着更好的性能。在少数情况下,它会导致性能下降。您必须检查系统上的所有其他进程 运行ning 是什么?你有多少 CPU 个内核?
如果您有双核处理器并且 运行 8 个线程意味着 java 需要更多工作来协调线程之间的关系。 为获得最佳性能,请尝试 运行在您的 PC/server.
上使用与 CPU 核心数量相同的线程数,并在您的 PC/server 上使用最少的服务 运行ning通过在 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();
}
}
这并不是一个很好的方法,但您应该会看到执行时间的显着改善。不同之处在于,现在您正在启动所有线程中的所有计算,然后开始收集结果。