使用浮动时,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 ==============