【发布时间】:2025-11-29 17:00:01
【问题描述】:
所以,我在 java 中练习多线程,并尝试按顺序和使用 4 个线程添加随机生成的 2D 整数数组的元素。我测量了我的代码的性能,出于某种原因,顺序部分比多线程快得多。下面是顺序加法的代码:
public class ArraySum2DNonMT {
private int[][] arrayToSum;
private int totalSum;
public ArraySum2DNonMT(int[][] arr){
this.arrayToSum = arr;
this.setTotalSum(0);
}
public void runSequential(){
for(int i = 0; i < arrayToSum[0].length; i++){
for(int j = 0; j < arrayToSum.length; j++){
setTotalSum(getTotalSum() + arrayToSum[j][i]);
}
}
}
public int getTotalSum() {
return totalSum;
}
public void setTotalSum(int totalSum) {
this.totalSum = totalSum;
}
}
这里是多线程版本的代码:
package multiThreaded;
/**
*
* @author Sahil Gupta
*
* This class takes in a 2D integer array and adds it's contents. This
* addition will be concurrent between several threads which will divide
* the work of the array based on the threadID assigned to thread by the
* programmer. Assume that the passed in 2D array to the constructor is a
* matrix with each array in the main array having same length.
*/
public class ArraySum2D implements Runnable{
private int[][] arrayToSum;
private int threadID;
private int totalSum;
public ArraySum2D(int[][] arr, int threadID){
this.arrayToSum = arr;
this.threadID = threadID;
this.setTotalSum(0);
}
@Override
public void run() {
int arrayCol = arrayToSum[0].length;
int arrayRow = arrayToSum.length;
int colStart = (int)((threadID%2) * (arrayCol/2));
int rowStart = (int)((int)(threadID/2) * (arrayRow/2));
int colEnd = colStart + (int)(arrayCol/2);
int rowEnd = rowStart + (int)(arrayRow/2);
for(int i = colStart; i < colEnd; i++){
for(int j = rowStart; j < rowEnd; j++){
setTotalSum(getTotalSum() + arrayToSum[j][i]);
}
}
}
public int getTotalSum() {
return totalSum;
}
public void setTotalSum(int totalSum) {
this.totalSum = totalSum;
}
}
这里是主要的:
package controller;
import java.util.Random;
import multiThreaded.ArraySum2D;
import sequentialNonMT.ArraySum2DNonMT;
public class ControllerMain {
private final static int cols = 20;
private final static int rows = 10;
private static volatile int[][] arrayToAdd = new int[rows][cols];
private static Random rand = new Random();
private static ArraySum2D a0, a1, a2, a3;
public static void main(String[] args) throws InterruptedException{
for(int j = 0; j < rows; j++){
for(int i = 0; i < cols; i++){
arrayToAdd[j][i] = rand.nextInt(100);
}
}
ArraySum2DNonMT a = new ArraySum2DNonMT(arrayToAdd);
long startTimeSequential = System.nanoTime();
a.runSequential();
long estimatedTimeSequential = System.nanoTime() - startTimeSequential;
System.out.println("The total sum calculated by sequential program is: " + a.getTotalSum());
System.out.println("The total time taken by sequential program is: " + estimatedTimeSequential);
a0 = new ArraySum2D(arrayToAdd, 0);
a1 = new ArraySum2D(arrayToAdd, 1);
a2 = new ArraySum2D(arrayToAdd, 2);
a3 = new ArraySum2D(arrayToAdd, 3);
Thread t0 = new Thread(a0);
Thread t1 = new Thread(a1);
Thread t2 = new Thread(a2);
Thread t3 = new Thread(a3);
long startTimeMultiThreaded = System.nanoTime();
t0.start();
t1.start();
t2.start();
t3.start();
t0.join();
t1.join();
t2.join();
t3.join();
int Sum = addThreadSum();
long estimatedTimeMultiThreaded = System.nanoTime() - startTimeMultiThreaded;
System.out.println("The total sum calculated by multi threaded program is: " + Sum);
System.out.println("The total time taken by multi threaded program is: " + estimatedTimeMultiThreaded);
}
private static int addThreadSum(){
return a0.getTotalSum() + a1.getTotalSum() + a2.getTotalSum() + a3.getTotalSum();
}
}
我目前得到的输出显示了运行时的显着差异(此处以纳秒为单位测量)。这是我得到的:
The total sum calculated by sequential program is: 10109
The total time taken by sequential program is: 46000
The total sum calculated by multi threaded program is: 10109
The total time taken by multi threaded program is: 641000
顺序代码大约快 13 倍。你能帮我指出我可能做错了什么吗?我有一个双核 i7 haswell,macbook air。我不确定为什么需要更长的时间,但我想到了一些可能导致此问题的想法:错误共享、过多的并行/线程(双核为 4 个)、缓存一致性协议可能对我不利,我缺少/不知道的其他一些基本多线程的东西。
请帮助我确定使多线程运行比顺序运行更快的具体原因和方法。非常感谢您帮助我!
编辑:有关处理器及其缓存的更多信息: 处理器名称:英特尔酷睿 i7 处理器速度:1.7 GHz 处理器数量:1 核心总数:2 L2 缓存(每核):256 KB 三级缓存:4 MB
根据英特尔的数据表,我认为它最多可以有 4 个线程。
附:这是我第一篇提问的帖子,但我一直在使用这个网站来消除疑惑。请原谅我犯的任何错误。
【问题讨论】:
-
除非我是个智障,否则你将把每个线程花费的时间加起来......并结合起来。将它们加在一起可以得到比实际时间长近 4 倍的值,因为它们同时/并行运行,而不是一个接一个地运行。
-
这似乎是一个非常小的基准数据集。由于实际计算时间如此之少,因此线程中的额外设置代码可能会有所不同。尝试大量数据,看看结果是否不同。
-
嗨@BrantUnger,我不同意你所说的。我计算时间的方法是获取代码开始执行之前的系统时间和代码停止执行时的系统时间。我认为这是应该这样做的。当我尝试您所说的时,所花费的时间是相同的。但感谢您的意见!
-
@JamesMontagne 谢谢!我同意。它确实缩短了时间,并通过数百万个元素的输入大小给了我预期的结果。尽管程序没有像多线程预期的那样运行四倍,但它的运行速度确实快了 2-2.5 倍。还有其他建议吗?
标签: java arrays multithreading performance