简体   繁体   English

迭代与递归效率

[英]Iteration vs Recursion efficiency

I got a basic idea of how recursion works - but I've always programmed iteratively. 我对递归的工作原理有一个基本的了解-但我始终会进行迭代编程。

When we look at the keywords CPU/stack/calls and space, how is recursion different from iterations? 当我们查看关键字CPU / stack / calls和space时,递归与迭代有何不同?

It needs more memory because of running many "stacks(?)" which each (most likely) stores a value. 由于运行许多“堆栈(?)”(每个堆栈(最有可能)存储一个值),因此需要更多的内存。 It therefore takes up much more space, than an iterative solution to the same problem. 因此,与迭代解决同一问题相比,它占用了更多的空间。 This is generally speaking. 通常来说。 There are some cases where Recursion would be better, such as programming Towers of Hanoi and such. 在某些情况下,递归会更好,例如,对河内塔进行编程等。

Am I all wrong? 我都错了吗? I've got an exam soon and I have to prepare a lot of subjects. 我很快就要考试了,我必须准备很多科目。 Recursion is not my strong suit, so I would appreciate some help on this matter :) 递归不是我的强项,所以我希望在此问题上有所帮助:)

This really depends on the nature of the language and compiler/interpreter. 这实际上取决于语言和编译器/解释器的性质。

Some functional languages implement tail recursion , for example, to recognize specific cases where the stack frame can be destroyed/freed prior to recursing into the next call. 某些功能语言实现了尾部递归 ,例如,以识别在递归到下一个调用之前可以销毁/释放堆栈帧的特定情况。 In those special cases among the languages/compilers/interpreters that support it, you can actually have infinite recursion without overflowing the stack. 在支持它的语言/编译器/解释器中的特殊情况下,实际上您可以进行无限递归而不会导致堆栈溢出。

If you're working with languages that use the hardware stack and don't implement tail recursion, then typically you have to push arguments to the stack prior to branching into a function and pop them off along with return values, so there's somewhat of an implicit data structure there under the hood (if we can call it that). 如果您使用的是使用硬件堆栈的语言,并且未实现尾递归,那么通常您必须在将参数分支到函数之前将参数推入堆栈,然后将它们与返回值一起弹出,因此有些隐藏的数据结构(如果可以这样称呼)。 There's all kinds of additional things that can happen here as well, like register shadowing to optimize it. 这里还可能发生各种各样的事情,例如通过寄存器阴影对其进行优化。

The hardware stack is usually very efficient, typically just incrementing and decrementing a stack pointer register to push and pop, but it does involve a bit more state and instructions than branching with a loop counter or a condition. 硬件堆栈通常非常高效,通常只是增加和减少堆栈指针寄存器以进行压入和弹出操作,但与使用循环计数器或条件分支相比,它涉及的状态和指令要多得多。 Perhaps more importantly, it tends to involve more distant branching to jump into another function's code as opposed to looping within the same body of code which could involve more instruction cache and page misses. 也许更重要的是,它倾向于涉及更远的分支以跳转到另一个函数的代码中,而不是在同一代码体内循环可能会涉及更多的指令高速缓存和页面丢失。

In these types of languages/compilers/interpreters that use the hardware stack and will always overflow it with enough recursion, the loopy routes often provide a performance advantage (but can be more tedious to code). 在使用硬件堆栈并且将始终以足够的递归方式使其溢出的这些类型的语言/编译器/解释器中,循环路由通常会提供性能优势(但对代码而言可能更为繁琐)。

As a twist, you also have aggressive optimizers sometimes which do all kinds of magic with your code in the process of translating it to machine instructions and linking it like inlining functions and unrolling loops, and when you take all these factors into account, it's often better to just code things a bit more naturally and then measure with a profiler if it could use some tweaking. 作为一种转折,有时您还会拥有一些激进的优化器,这些优化器会在将代码转换为机器指令并进行链接(如内联函数和展开循环)的过程中对代码进行各种魔术处理,而当您考虑所有这些因素时,通常最好只是更自然地编写代码,然后使用探查器进行测量(如果可以进行一些调整)。 Of course you shouldn't use recursion in cases that can overflow, but I generally wouldn't worry about the overhead most of the time. 当然,在可能发生溢出的情况下,您不应该使用递归,但是我通常不会担心大部分时间的开销。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM