Scala并行用于RAM耗尽

时间:2012-02-09 07:47:46

标签: scala parallel-collections

因此,对于家庭作业,我应该使用一个简单的集成一个应该导致pi的函数来使用多个线程机制。该实现应该处理超过500亿的间隔。我当前的实现在堆大小为2GB时处理for循环高达约5000万。现在我的问题是为什么实现使用这么多内存? (我认为这是因为范围必须提前制作,这是真的吗?)我如何改善内存使用?是否可以使用并行集合或我被迫使用线程池来做这样的事情?

注意:我将获得以下实施的全部功劳。这是出于我的求知欲和我对scala更流利的梦想。

import scala.Math

object Pi {
 def calculate_pi(interval: Int): Double = {
    val start: Long = System.currentTimeMillis;
    var duration: Long = 0
    var x: Double = 2.0/interval
    var y: Double = 0.0
    var mypi: Double = 0.0

    (x until 1.0 by 1.0/interval).par.foreach(i => {
       y = 4.0/(1.0+x*x)
       mypi += (1.0/interval)*y
     })

   duration = (System.currentTimeMillis - start)
   println("scala calculate_pi\t" + interval + "\t" + duration + "ms\t" + mypi)
   return mypi
 }




object Main extends App {
  println("Please input the interval for the calculation")
  if(args.length < 1) { sys.exit }
  val interval = args(0).toInt 
  Pi.calculate_pi_seq(interval)
  Pi.calculate_pi(interval)
}

2 个答案:

答案 0 :(得分:6)

这是各种错误:

(x until 1.0 by 1.0/interval).par.foreach(i => {
   y = 4.0/(1.0+x*x)
   mypi += (1.0/interval)*y
 })

第一个问题是y的所有计算都是相同的:您在计算它时没有使用i。由于x没有变化,所有线程都会计算相同的值。

这是第二个问题,您正在并行计算mypi(和y 。这意味着多个线程同时读取和写入mypiy

让我们考虑一次执行来理解其中的问题。我们假设第一个线程开始运行,计算y然后读取ymypi。该线程然后暂停,所有其他线程运行。最后,该线程恢复并将其计算结果写入mypi。在这种情况下,所有其他线程的所有计算都被浪费了,因为最终值是由该一个线程给出的。

这是一个简单的案例。基本上,您无法预测每个读取和写入mypi会发生什么(y更容易,因为所有线程都为它分配相同的值)。

而且,是的,当您在.par上致电NumericRange时,会创建一个包含NumericRange所有值的集合。

答案 1 :(得分:-3)

我不知道底层应用程序,我通过实验了解到,如果你在par上使用方法Range(例如),它会提前实例化,正如你所指出的那样。

但是,您似乎只使用集合来利用并行化。换句话说,要计算一段与集合本身有些无关的代码 - 值i甚至没有被使用。因此,foreach循环非常冗余,因为您只对y和x值感兴趣。对于一个简单的for循环可以完成的事情来说,这似乎是一项大量的工作。

那说scala中其他类型的并行化非常简单。用演员怎么样?它们重量轻,非常简单。否则,工作线程甚至Java线程都可能起到作用。