3

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

注意:我将通过以下实现获得充分的信任。这是为了我的求知欲和我在 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)
}
4

2 回答 2

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计算(and y) 。这意味着多个线程同时读取和写入mypiy

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

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

而且,是的,当您调用.para时NumericRange,它会创建一个包含 that 的所有值的集合NumericRange

于 2012-02-09T12:55:42.973 回答
-3

在不了解底层应用程序的情况下,我通过实验了解到,如果您parRange(例如)上使用该方法,它会提前实例化,正如您所指出的那样。

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

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

于 2012-02-09T10:32:32.393 回答