Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用浮动时,Scala foldLeft的性能比for loop差4倍_Scala - Fatal编程技术网

使用浮动时,Scala foldLeft的性能比for loop差4倍

使用浮动时,Scala foldLeft的性能比for loop差4倍,scala,Scala,有更广泛的学科知识的人能解释一下吗 var acc = 0.0 for (i <- 0 until 100) acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1) 我更喜欢功能性版本,只是不太了解性能。有什么方法可以优化这个或是一个foldLeft备选方案吗?首先,这个例子太小,无法获得准确的基准。从这些数字你真的看不出什么。您还必须控制JVM预热之类的事情,这将完全抵消您得到的任何数字 也就是说,您可以查看源代码以了解这些东西是如何实现的。特

有更广泛的学科知识的人能解释一下吗

var acc = 0.0
for (i <- 0 until 100)
    acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1)

我更喜欢功能性版本,只是不太了解性能。有什么方法可以优化这个或是一个
foldLeft
备选方案吗?

首先,这个例子太小,无法获得准确的基准。从这些数字你真的看不出什么。您还必须控制JVM预热之类的事情,这将完全抵消您得到的任何数字

也就是说,您可以查看源代码以了解这些东西是如何实现的。特别是,
Range
foldLeft
TraversableOnce
上定义,您可以查看:

正如您所看到的,
foldLeft
只是授权给
foreach
,这正是(…)语法所解析的

换句话说,他们实际上在做同样的事情


一般的规则是,除非进行大量的计算,否则在这种情况下,您可能不会看到真正的性能差异。如果这确实是一个问题,最快的方法就是使用
while
循环。

这里有一个简单的递归版本:

@tailrec
final def rec(i:Int, max:Int, acc:Double): Double = 
  if (i == max) acc else rec(i+1, max, acc + 4.0 * (1 - (i % 2) * 2) / (2 * i + 1))
我通过Calipher运行了这些方法和一个递归方法,使用这个,大小为1001000,…,10000000。结果如下:

[info]   length benchmark        ns linear runtime
[info]      100       For       893 =
[info]      100  FoldLeft      1447 =
[info]      100       Rec       888 =
[info]     1000       For     10540 =
[info]     1000  FoldLeft     20322 =
[info]     1000       Rec     11048 =
[info]    10000       For    115499 =
[info]    10000  FoldLeft    255171 =
[info]    10000       Rec    116690 =
[info]   100000       For   1268198 =
[info]   100000  FoldLeft   2223178 =
[info]   100000       Rec   1114504 =
[info]  1000000       For  11985576 =
[info]  1000000  FoldLeft  23916076 ==
[info]  1000000       Rec  11993123 =
[info] 10000000       For 114804171 ==============
[info] 10000000  FoldLeft 244991000 ==============================
[info] 10000000       Rec 119422600 ==============

请注意,功能性的、非变异的递归版本几乎与for循环(win的尾部递归)一样快。另外,请注意foldLeft版本的速度大约是foldLeft版本的两倍。

对可变数据的操作几乎(如果不是)总是比不可变数据结构快,因此第一个示例的速度更快也就不足为奇了。谢谢。因此,使用while仍然是必要的,那么我认为呢?是的,通常有一种难看/容易出错的方式来编写东西,但在几乎所有情况下,编写更干净、更安全的代码更好。你应该只在真正需要的时候才考虑这些微优化。实际上,在我的特殊情况下,你的解决方案比for循环快40%。干得好,谢谢。
@tailrec
final def rec(i:Int, max:Int, acc:Double): Double = 
  if (i == max) acc else rec(i+1, max, acc + 4.0 * (1 - (i % 2) * 2) / (2 * i + 1))
[info]   length benchmark        ns linear runtime
[info]      100       For       893 =
[info]      100  FoldLeft      1447 =
[info]      100       Rec       888 =
[info]     1000       For     10540 =
[info]     1000  FoldLeft     20322 =
[info]     1000       Rec     11048 =
[info]    10000       For    115499 =
[info]    10000  FoldLeft    255171 =
[info]    10000       Rec    116690 =
[info]   100000       For   1268198 =
[info]   100000  FoldLeft   2223178 =
[info]   100000       Rec   1114504 =
[info]  1000000       For  11985576 =
[info]  1000000  FoldLeft  23916076 ==
[info]  1000000       Rec  11993123 =
[info] 10000000       For 114804171 ==============
[info] 10000000  FoldLeft 244991000 ==============================
[info] 10000000       Rec 119422600 ==============