用于耗尽 RAM 的 Scala 并行



所以对于家庭作业,我应该使用几个线程机制,使用一个简单的函数集成,应该产生pi。该实施应该处理超过5000亿的间隔。我当前的实现在 2GB 的堆大小上处理多达大约 5000 万个 for 循环。现在我的问题是为什么实现使用这么多内存?(我认为这是因为范围必须提前确定,这是真的吗?如何提高内存使用率?是否可以使用并行集合,或者我是否被迫使用线程池进行此类操作?

注意:我将通过以下实现获得全部荣誉。这是为了我的求知欲和我对斯卡拉语更流利的梦想。

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_pit" + interval + "t" + duration + "mst" + 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)
}

这是各种错误:

(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更容易,因为所有线程都为其分配相同的值(。

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

由于不知道底层应用程序,我通过实验了解到,如果您使用该方法par Range(例如(,它会提前实例化,正如您所指出的。

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

也就是说,其他类型的并行化在scala中非常容易。使用演员呢?它们重量轻且非常简单。否则,工作线程甚至 Java 线程可能会解决问题。

相关内容

  • 没有找到相关文章

最新更新