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

注意:我将在以下实施中获得全部功劳。这是出于我的求知欲和我的梦想,使他在流言ala语中变得更加流利。

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

最佳答案

这是各种各样的错误:

(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的所有值的集合。

07-26 03:29