对于一个赋值,我必须实现一个Java程序,当用多个线程运行时实际上比只有1个慢。我知道创建一个线程需要一些开销,但在这个例子中我处理的是一个大数组20,000x20,000 。没有依赖关系,所以创建4个较小的块并同时运行它们的好处应该总是超出创建线程的成本吗?
for (int i = 0; i < numThreads; i++) {
// for each iteration of the body's for loop,
// calculate the starting and ending indexes
// of the ith chunk of the y dimension of
// the anArray array
final int indexStart = i * chunkSize;
final int indexEnd = (i + 1) * chunkSize;
// each "execute" method of the Executor class
// creates a new object of type Runnable ...
// be careful with the parentheses here ... the
// entire next code block is being passes
// as a parameter to the execute method
ex.execute(new Runnable() {
// The run() method is declared abstract in the Runnable
// class, so it MUST be overriden. The body of the
// run method is the "code" that each thread executes
@Override
public void run() {
for (int j=0; j<anArray.length; j++){
for (int k = indexStart; k < indexEnd; k++){
anArray[j][k] = anArray[j][k] * anArray[j][k] / 3.45 * Math.sqrt(anArray[j][k]);
}
} // end for
} // end run
}
);
}
我们的任务是只修改最里面的for循环,我们可以在那里做任何我们想要的但是当用更多线程执行时它必须使运行时更慢。上限为8个线程。 我真正的问题是在实现多个线程时会导致更多的问题。我做了一些研究,发现你可以使用单个线程来使用大部分cpu,这样可以创造更多的帮助,这是怎么回事。
答案 0 :(得分:2)
我做了一些研究,发现你可以使用单个线程来使用大部分cpu,这样可以创造更多的帮助,这是怎么回事。
多个线程在独立运行时效果最佳。这意味着任何过度使用共享资源都会限制甚至使多个线程使用速度变慢。
假设您有一个4核的Socket。这意味着您有4个内核,每个内核具有32 KB的L1缓存。如果你使用的内存超过这个数量,他们必须使用速度大约3-4倍的二级缓存。但这些只有256 KB的内存。如果您使用的不仅仅是这个,他们必须使用一个且只有一个L3缓存。即使用超过1 MB的内存,您的应用程序不再缩放,可能会更慢。
在您的情况下,您还使用浮点单元esp Math.sqrt,它占用了相当多的CPU。每个核心只有一个FPU,因此您可能会发现使用超线程不会有太大帮助。 (可能<10%)
简而言之,鉴于您的浮点运算非常昂贵,我希望您应该获得良好的可扩展性,直到您拥有的核心数。随着您获得更多内核,在某些时候您的L3缓存将成为瓶颈。例如对于18个核心,您可能会发现这个问题。
答案 1 :(得分:2)
1个线程何时运行速度比多个线程并发运行的速度快。
以下是一些:
如果您正在创建自己的线程:当创建和启动N个线程并在每个线程上运行M任务所花费的时间大于在单个线程上运行N * M任务所花费的时间。提示:启动Java线程非常昂贵。
如果您在执行任务时花费大量时间来安排任务,则使用Executor
。
当你有相对于核心数的线程太多时。提示:多线程(对于计算绑定任务)可以获得的加速速度受到内核数量的限制,而不受线程数量的限制。
当任务具有固有的并发性瓶颈时,例如访问/更新常见的同步数据结构。
当任务涉及跨多个线程访问大量内存单元时,会出现大量内存缓存未命中和内存争用。
当您在基准测试中犯了错误时;例如当你没有适当考虑&#34; JVM热身&#34;的效果。
在这种情况下,我认为多线程比单线程更好,因为我们有更多内核。 100个线程1核心VS 100个线程4个核心。
如果你有4个核心,那么在这个例子中运行100个线程不会给你比4个线程更多的加速。现在添加一个事实,即你有开始96个没有帮助的线程的开销......这可以解释为什么多个(100个)线程比单个线程更慢。
此外,您的示例似乎可能会产生大量缓存未命中和内存流量。它看起来你将读取和写入具有4亿个元素的数组数组中的每个单元格。内存争用将成为瓶颈。