因此,对于一项家庭作业,我应该使用一种简单的函数集成(应该产生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
)。这意味着多个线程正在同时读取和写入mypi
和y
。让我们考虑一个执行来理解其中的问题。假设第一个线程开始运行,计算
y
,然后读取y
和mypi
。然后该线程暂停,所有其他线程运行。最后,该线程恢复并将其计算结果写入mypi
。在这种情况下,所有其他线程的所有计算都被浪费了,因为最终值是由那个线程给定的。那是一个简单的例子。基本上,您根本无法预测对
mypi
进行的每次读写操作(由于所有线程都为其分配了相同的值,因此y
更加容易)。而且,是的,当您在
.par
上调用NumericRange
时,它将创建一个包含该NumericRange
的所有值的集合。