递归GO vs Scala
以下Scala代码在1.5分钟内完成,而GO finish中的等效代码在2.5分钟内完成。递归GO vs Scala,scala,go,fibonacci,Scala,Go,Fibonacci,以下Scala代码在1.5分钟内完成,而GO finish中的等效代码在2.5分钟内完成。 最多fib(40)都需要2秒。间隙出现在fib(50) 我得到的印象是,作为本地人,GO应该比Scala更快 斯卡拉 去 Scala优化? 戈朗极限 正如“我的另一辆车是cadr”所说的,问题是“为什么Scala在这个特殊的微基准上比GO快?” 忘记斐波那契吧,假设我有一个需要递归的函数。 Scala在递归情况下更优越吗 它可能是一个内部编译器实现,甚至是特定于Scala的优化。 如果你知道,请回答 在1
最多fib(40)都需要2秒。间隙出现在fib(50)
我得到的印象是,作为本地人,GO应该比Scala更快 斯卡拉 去 Scala优化?
戈朗极限 正如“我的另一辆车是cadr”所说的,问题是“为什么Scala在这个特殊的微基准上比GO快?” 忘记斐波那契吧,假设我有一个需要递归的函数。
Scala在递归情况下更优越吗 它可能是一个内部编译器实现,甚至是特定于Scala的优化。
如果你知道,请回答 在12秒内循环运行1500000000次
Scala解决方案将使用堆栈,因为它不是尾部递归的(添加发生在递归调用之后),但它不应该创建任何垃圾 对于这种代码模式,您正在使用的热点编译器(可能是服务器)很可能是比Go编译器更好的编译器
如果你真的很好奇,你可以。对于Go,使用迭代而不是递归。递归可以用显式堆栈的迭代来代替。它避免了函数调用和调用堆栈管理的开销。例如,使用迭代并将
n
从50增加到1000几乎不需要时间:
package main
import "fmt"
func fib(n int) (f int64) {
if n < 0 {
n = 0
}
a, b := int64(0), int64(1)
for i := 0; i < n; i++ {
f = a
a, b = b, a+b
}
return
}
func main() {
n := 1000
fmt.Println(n, fib(n))
}
使用适当的算法。避免指数时间复杂性。当性能很重要时,不要对斐波那契数使用递归
参考:
我们观察到分支递归算法的计算效率低下
几乎所有的教科书都没有适当地涵盖函数
计算机科学课程在课程的前三年。
斐波那契数和二项式系数常用作
分支递归函数的示例。然而,他们的收入呈指数增长
时间复杂性很少有人提出,也从未在实践中得到完全证明
教科书。很少使用替代线性时间迭代解
提到。我们给出了这些递归函数的简单证明
具有指数时间复杂度
递归是定义和算法的有效技术
只进行一次递归调用,但如果
它进行两个或更多递归调用。因此,递归方法是可行的
通常作为概念性工具而不是工具更有用
高效的计算工具。本文给出的证明是正确的
成功地(在五年期间)向一年级学生授课
在渥太华大学。有人建议将递归作为
第二部分将介绍问题解决和定义工具
第一门计算机科学课程。然而,递归编程应该
推迟到课程结束时(或者最好在
第二门计算机科学课程的开始),迭代之后
程序被很好地掌握,堆栈操作也被很好地理解
我看不到任何优化,它是指数的,递归斐波那契的同一个例子被用来说明如何不编写递归函数。看起来,这种效果是因为一些实现的细微差别,可能是垃圾收集,可能是进程可用的内存(比如,出于某种原因,在scala中,对于任务和go-not来说,它已经足够了)。我会在峰值检查内存消耗。因为Scala是JIT编译的,所以它可以在几个递归调用之后执行一些特别的内存化。我已经让JVM在循环展开方面做了一些非常好的优化。虽然go代码被编译成机器代码,但运行时仍然进行所有内存和堆栈管理,所以JVM基本上是一样的。我并不惊讶JVM比go优化得更好。问题不是“我如何才能更快地计算斐波那契”。问题是“为什么Scala在这个特殊的微基准中比GO快”。@Myothercarisacadr:仔细阅读这个问题。这个问题问的是从fib(40)到fib(50)的时间跳跃,从2秒到1.5到2.5分钟。这个答案为围棋解决了这个问题。对于Scala来说,这可能是一个类似的答案。如果可以的话,你应该始终使用迭代——递归是懒惰的程序员工具。我不完全同意。您可以通过递归获得相同的复杂性,因为您可以。
func fib(n int) (ret int) {
if n > 1 {
return fib(n-1) + fib(n-2)
}
return n
}
func fib(n int) (two int) {
one := 0
two = 1
for i := 1; i != n; i++ {
one, two = two, (one + two)
}
return
}
package main
import "fmt"
func fib(n int) (f int64) {
if n < 0 {
n = 0
}
a, b := int64(0), int64(1)
for i := 0; i < n; i++ {
f = a
a, b = b, a+b
}
return
}
func main() {
n := 1000
fmt.Println(n, fib(n))
}
$ time .fib
1000 8261794739546030242
real 0m0.001s
user 0m0.000s
sys 0m0.000s