2016-02-18 58 views
1

对于一个分配,我必须实现一个Java程序,当它与多个线程一起运行实际上比只有1时慢。我知道创建线程需要一些开销,但在本例中我正在处理20,000 x 20,000的大数组。没有依赖关系,所以创建4个较小的块并同时运行它们的好处应该始终超出创建线程的成本吗?什么时候1个线程的运行速度会比多个线程同时运行的要快

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 
    } 
    ); 
} 

我们的任务是修改只有最里面的循环中,我们可以做什么都希望我们在那里,但它有当多个线程执行,使运行速度较慢。具有8个线程的上限。 我真正的问题是在实现多个线程时可能导致更多的问题。我已经做了一些研究,发现你可以使用单线程来使用大多数的CPU,所以创建更多不会帮助,这怎么可能。

+0

是否有可以创建的线程数的上限?如果没有,那么你可以在每次迭代(或其混合)上创建一个线程。 – txtechhelp

+0

应该是一个8的上限 – user3267256

+0

你说'*它必须使运行时运行速度较慢,执行时少线程*'。而你的头衔似乎相反......你想要什么? – smwikipedia

回答

2

我已经做了一些研究,发现你可以使用单线程的大部分CPU,所以创建更多不会帮助,这怎么可能。

多个线程独立运行时效果最佳。这意味着任何对共享资源的过度使用都会限制甚至使多线程使用速度变慢。

假设你有一个4核的Socket。这意味着你有4个核心,每个核心都有32KB的L1缓存。如果您使用的内存量超过这个数量,则必须使用速度降低3-4倍的L2缓存。但这些只有256 KB的内存。如果您使用的不止于此,则必须使用唯一的一个L3缓存。即使用超过1 MB的内存,并且您的应用程序不再缩放,速度可能会变慢。

在你的情况,你也使用浮点单元esp Math.sqrt,它需要相当多的CPU。每个内核只有一个FPU,所以你很可能会发现使用超线程技术不会有太大帮助。 (或许< 10%)

总之,由于你的浮点运算非常昂贵,我认为你应该获得良好的可扩展性,直到你拥有的核心数量。当你获得更多内核时,你的L3缓存将成为瓶颈。例如对于18个内核,您可能会发现这是一个问题。

+0

好。我第一次听说L1,L2,L3缓存。我会探索他们:) –

2

什么时候1个线程的运行速度会比多个线程同时运行快。

这里有一些:

  1. 如果您正在创建自己的主题:当所花费的时间来创建和启动N个线程和运行中号任务,每个比运行n个时间大*单个线程上的M个任务。提示:启动Java线程非常昂贵。

  2. 如果您在使用Executor计划任务所花费的时间很大,以执行任务。

  3. 当你有太多的线程相对于核心的数量。提示:多线程(对于计算绑定任务)可以获得的加速受限于内核数量,而不受线程数量的限制。

  4. 当任务具有固有的并发瓶颈时,如访问/更新公共同步数据结构。

  5. 当任务涉及跨多个线程访问大量内存单元,并且会导致大量内存缓存未命中和内存争用。

  6. 如果您在基准测试中犯了错误,例如当你没有适当考虑“JVM热身”效应时。


在这种情况下,我认为多线程比单线程更好,因为我们有更多的内核。 100螺纹1芯VS 100螺纹4芯。

如果你有4个内核,那么在这个例子中运行100个线程不会比4个线程提供更多的加速。现在添加一个事实,即您有开始96个线程的开销,这些开销并没有帮助...并且这可以解释为什么多个(100)线程比单个线程的

此外,您的示例可能会产生大量的缓存未命中和内存流量。看起来你将会读取和写入4亿个元素的数组中的每个单元格。内存争用成为瓶颈。

+0

好的总结。我对第3点有一个疑问。在这种情况下,我认为多线程比单线程更好,因为我们有更多的内核。 100螺纹1芯VS 100螺纹4芯。 –

相关问题