我只是在 4 核机器上运行一些多线程代码,希望它比在单核机器上更快。想法是这样的:我有固定数量的线程(在我的例子中每个核心一个线程)。每个线程执行一个Runnable
形式:
private static int[] data; // data shared across all threads
public void run() {
int i = 0;
while (i++ < 5000) {
// do some work
for (int j = 0; j < 10000 / numberOfThreads) {
// each thread performs calculations and reads from and
// writes to a different part of the data array
}
// wait for the other threads
barrier.await();
}
}
在四核机器上,此代码执行worse4 个线程比 1 个线程好。即使与CyclicBarrier
的开销,我本以为代码的执行速度应该至少快 2 倍。为什么它运行slower?
编辑:这是我尝试过的繁忙等待实现。不幸的是,它使程序在更多内核上运行得更慢(也在一个单独的问题中讨论)here https://stackoverflow.com/questions/6553044/java-implementing-a-busy-wait-mechanism):
public void run() {
// do work
synchronized (this) {
if (atomicInt.decrementAndGet() == 0) {
atomicInt.set(numberOfOperations);
for (int i = 0; i < threads.length; i++)
threads[i].interrupt();
}
}
while (!Thread.interrupted()) {}
}
添加更多线程不一定能保证提高性能。额外线程导致性能下降的可能原因有很多:
- 粗粒度锁定可能会过度序列化执行 - 也就是说,锁定可能会导致一次仅运行一个线程。您可以获得多线程的所有开销,但没有任何好处。尝试减少锁的持有时间。
- 这同样适用于过于频繁的障碍和其他同步结构。如果内
j
循环很快完成,您可能会在屏障中度过大部分时间。尝试在同步点之间做更多的工作。
- 如果您的代码运行得太快,可能没有时间将线程迁移到其他 CPU 核心。除非您创建大量生命周期非常短的线程,否则这通常不是问题。使用线程池,或者简单地给每个线程更多的工作会有所帮助。如果每个线程运行时间超过一秒左右,这不太可能成为问题。
- 如果您的线程正在处理大量共享读/写数据,则缓存行弹跳可能会降低性能。也就是说,虽然这通常会导致性能下降,但仅此一点不太可能导致性能比单线程情况更差。尝试确保每个线程写入的数据与其他线程的数据按照缓存行的大小(通常约为 64 字节)分开。特别是,不要将输出数组布置为
[thread A, B, C, D, A, B, C, D ...]
由于您尚未显示代码,因此我无法在这里详细说明。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)