[英]Java Multithreaded vector addition
我正在尝试熟悉Java多线程应用程序。 我试图考虑一个可以很好地并行化的简单应用程序。 我认为矢量加法将是一个很好的应用程序。 但是,在我的Linux服务器(具有4个内核)上运行时,我没有任何提高的速度。 在4,2,1线程上执行的时间大致相同。
这是我想出的代码:
public static void main(String[]args)throws InterruptedException{
final int threads = Integer.parseInt(args[0]);
final int length= Integer.parseInt(args[1]);
final int balk=(length/threads);
Thread[]th = new Thread[threads];
final double[]result =new double[length];
final double[]array1=getRandomArray(length);
final double[]array2=getRandomArray(length);
long startingTime =System.nanoTime();
for(int i=0;i<threads;i++){
final int current=i;
th[i]=new Thread(()->{
for(int k=current*balk;k<(current+1)*balk;k++){
result[k]=array1[k]+array2[k];
}
});
th[i].start();
}
for(int i=0;i<threads;i++){
th[i].join();
}
System.out.println("Time needed: "+(System.nanoTime()-startingTime));
}
长度始终是线程的倍数,并且getRandomArray()创建一个介于0和1之间的双精度数组。
1-线程的执行时间:84579446ns
2线程执行时间:74211325ns
4线程执行时间:89215100ns
长度= 10000000
这是getRandomArray()的代码:
private static double[]getRandomArray(int length){
Random random =new Random();
double[]array= new double[length];
for(int i=0;i<length;i++){
array[i]=random.nextDouble();
}
return array;
}
我将不胜感激任何帮助。
对于以下代码,可以观察到差异。 试试吧。
public static void main(String[]args)throws InterruptedException{
for(int z = 0; z < 10; z++) {
final int threads = 1;
final int length= 100_000_000;
final int balk=(length/threads);
Thread[]th = new Thread[threads];
final boolean[]result =new boolean[length];
final boolean[]array1=getRandomArray(length);
final boolean[]array2=getRandomArray(length);
long startingTime =System.nanoTime();
for(int i=0;i<threads;i++){
final int current=i;
th[i]=new Thread(()->{
for(int k=current*balk;k<(current+1)*balk;k++){
result[k]=array1[k] | array2[k];
}
});
th[i].start();
}
for(int i=0;i<threads;i++){
th[i].join();
}
System.out.println("Time needed: "+(System.nanoTime()-startingTime)*1.0/1000/1000);
boolean x = false;
for(boolean d : result) {
x |= d;
}
System.out.println(x);
}
}
首先,您需要预热代码。 这样,您将可以测量编译后的代码。 前两个迭代具有相同(大约)的时间,但下一个迭代将有所不同。 另外,我将double更改为boolean,因为我的机器内存不足。 这使我可以分配一个巨大的数组,这也使工作消耗更多的CPU。
评论中有一个链接。 我建议你阅读它。
您好,如果您尝试查看内核共享的工作方式,可以对所有内核执行非常简单的任务,但可以使它们在不同线程之间不共享的事物上持续工作(基本上是模拟例如合并排序,其中线程是处理复杂的事物并在短时间内使用共享资源)。 使用您的代码,我做了这样的事情。 在这种情况下,您应该看到几乎正好2倍的速度和4倍的速度。
public static void main(String[]args)throws InterruptedException{
for(int a=0; a<5; a++) {
final int threads = 2;
final int length = 10;
final int balk = (length / threads);
Thread[] th = new Thread[threads];
System.out.println(Runtime.getRuntime().availableProcessors());
final double[] result = new double[length];
final double[] array1 = getRandomArray(length);
final double[] array2 = getRandomArray(length);
long startingTime = System.nanoTime();
for (int i = 0; i < threads; i++) {
final int current = i;
th[i] = new Thread(() -> {
Random random = new Random();
int meaningless = 0;
for (int k = current * balk; k < (current + 1) * balk; k++) {
result[k] = array1[k] + array2[k];
for (int j = 0; j < 10000000; j++) {
meaningless+=random.nextInt(10);
}
}
});
th[i].start();
}
for (int i = 0; i < threads; i++) {
th[i].join();
}
System.out.println("Time needed: " + ((System.nanoTime() - startingTime) * 1.0) / 1000000000 + " s");
}
}
您会看到,在您的代码中,大部分时间都花在了构建大表上,然后线程执行得非常快,它们的工作是如此之快,以至于您计算时间是错误的,因为大部分时间都是通过创建线程来消耗的。 当我调用在预计算循环中工作的代码时,如下所示:
long startingTime =System.nanoTime();
for(int k=0; k<length; k++){
result[k]=array1[k]|array2[k];
}
System.out.println("Time needed: "+(System.nanoTime()-startingTime));
它的工作速度比使用2个线程的代码快两倍。 我希望您能理解我在这种情况下的意思,并且在我给我的主题多做一些毫无意义的工作时,会明白我的意思。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.