我正在写一个在Nehalem处理器上运行的多线程Java应用程序。然而,我有一个问题,从4个线程开始,我几乎没有看到我的应用程序中的加速。多线程的内存访问
我做了一些简单的测试。我创建了一个线程,它只分配一个大数组并访问数组中的随机条目。所以当我运行线程数时,运行时间不应该改变(假设我不超过可用CPU内核的数量)。但是我观察到,运行1或2个线程的时间几乎相同,但运行4或8个线程的速度要慢得多。因此,在尝试解决我的应用程序中的算法和同步问题之前,我想了解一下我可以实现的最大可能并行化。
我已经使用了-XX:+UseNUMA
JVM选项,所以数组应该分配在相应线程的内存中。
P.S.如果线程正在进行简单的数学计算,那么对于4线程甚至8线程就没有时间延迟,所以我得出结论,当线程访问内存时,我遇到了一些问题。
任何帮助或想法表示赞赏,谢谢。
编辑
感谢大家的回复。我看到我没有足够的自我解释。
在尝试消除我的应用程序中的同步问题之前,我做了一个简单的测试,检查可能实现的最佳可能并行化。代码如下:
public class TestMultiThreadingArrayAccess {
private final static int arrSize = 40000000;
private class SimpleLoop extends Thread {
public void run() {
int array[] = new int[arrSize];
for (long i = 0; i < arrSize * 10; i++) {
array[(int) ((i * i) % arrSize)]++; // randomize a bit the access to the array
}
long sum = 0;
for (int i = 0; i < arrSize; i++)
sum += array[i];
}
}
public static void main(String[] args) {
TestMultiThreadingArrayAccess test = new TestMultiThreadingArrayAccess();
for (int threadsNumber : new int[] { 1, 2, 4, 8 }) {
Statistics timer = new Statistics("Executing " + threadsNumber+ " threads"); // Statistics is a simple helper class that measures the times
timer.start();
test.doTest(threadsNumber);
timer.stop();
System.out.println(timer.toString());
}
}
public void doTest(int threadsNumber) {
Thread threads[] = new Thread[threadsNumber];
for (int i = 0; i < threads.length; i++) {
threads[i] = new SimpleLoop();
threads[i].start();
}
for (int i = 0; i < threads.length; i++)
try {
threads[i].join();
} catch (InterruptedException e) {
};
}
}
所以你看到没有同步在此MINITEST所有,也是阵列的分配线程内,因此应该放置在内存块,可以快速访问。此代码中也没有内存争用。仍然对于4个线程,运行时间下降30%,而8个线程运行速度下降两次。从代码中我可以等到所有线程完成他们的工作,并且由于他们的工作是独立的线程数量不应该影响执行所花费的总时间。
在机器上安装了2个四核超线程Nehalem处理器(总共16个CPU),因此每8个线程可以独占CPU。
当我试图用更小的数组(20K条目)运行此测试时,4个线程的执行时间下降了7%,8个线程下降了14%,这是令人满意的。但是当我尝试在大型阵列(40M条目)上随机访问时进行操作时,运行时间显着增加,所以我认为存在大块内存(因为它们不适合高速缓存内存?)在非有效的方法。
有没有任何想法如何解决这个问题?
希望能够以更好的方式阐明问题,再次感谢。
你可能想尝试一个更好的随机数发生器。然后您可以将数组大小与高速缓存大小绑定。 – 2010-07-15 12:38:52
看起来你的每个线程都在创建一个本地数组并在其上进行工作。这意味着当您增加测试中的线程数时,您可以增加正在完成的工作量,而不是增加处理相同数量数据的资源量。这就是为什么你看到缓慢下降。随着您减小阵列大小,执行时间的下降会减少,因为您正在减少通过添加新线程而创建的工作负载的增加。 – SpaceghostAli 2010-07-15 16:08:55
我并不是等待运行时间提高,我只是希望它对于不同数量的线程是相同的,因为它们中的每一个都应该使其在免费的CPU上工作。 – jutky 2010-07-16 06:11:20