Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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
Performance 迭代与递归效率_Performance_Recursion_Stack_Cpu - Fatal编程技术网

Performance 迭代与递归效率

Performance 迭代与递归效率,performance,recursion,stack,cpu,Performance,Recursion,Stack,Cpu,我对递归的工作原理有了一个基本的了解,但我总是迭代编程 当我们查看关键字CPU/堆栈/调用和空间时,递归与迭代有何不同 它需要更多的内存,因为运行许多“堆栈(?)”,每个(很可能)存储一个值。因此,它比同一问题的迭代解占用更多的空间。这是一般性的。在某些情况下,递归会更好,比如对河内的塔楼等进行编程 我全错了吗?我马上就要考试了,我得准备很多科目。递归不是我的强项,因此我希望在这方面能得到一些帮助:)这实际上取决于语言和编译器/解释器的性质 一些函数式语言实现尾部递归,例如,识别在递归到下一个调

我对递归的工作原理有了一个基本的了解,但我总是迭代编程

当我们查看关键字CPU/堆栈/调用和空间时,递归与迭代有何不同

它需要更多的内存,因为运行许多“堆栈(?)”,每个(很可能)存储一个值。因此,它比同一问题的迭代解占用更多的空间。这是一般性的。在某些情况下,递归会更好,比如对河内的塔楼等进行编程


我全错了吗?我马上就要考试了,我得准备很多科目。递归不是我的强项,因此我希望在这方面能得到一些帮助:)

这实际上取决于语言和编译器/解释器的性质

一些函数式语言实现尾部递归,例如,识别在递归到下一个调用之前可以销毁/释放堆栈帧的特定情况。在支持它的语言/编译器/解释器中的那些特殊情况下,实际上可以有无限递归而不会溢出堆栈

如果您使用的是使用硬件堆栈的语言,并且没有实现尾部递归,那么通常您必须在分支到函数之前将参数推送到堆栈,并将其与返回值一起弹出,因此在引擎盖下有某种隐式数据结构(如果我们可以这样称呼它的话)。这里还可能发生各种各样的其他事情,比如寄存器阴影来优化它

硬件堆栈通常是非常有效的,通常只是增加和减少堆栈指针寄存器以进行push和pop,但它确实涉及到比使用循环计数器或条件分支更多的状态和指令。也许更重要的是,它往往涉及到更遥远的分支,以跳转到另一个函数的代码,而不是在同一代码体中循环,这可能涉及更多的指令缓存和页面丢失

在这些使用硬件堆栈的语言/编译器/解释器类型中,循环路由通常会提供性能优势(但对代码来说可能更繁琐)


作为一个转折点,有时你也会有激进的优化器,在将代码翻译成机器指令并将其链接(如内联函数和展开循环)的过程中,优化器会对代码施加各种魔法,当你考虑到所有这些因素时,通常,最好只是更自然地编写代码,然后使用分析器进行测量,如果可以进行一些调整的话。当然,您不应该在可能溢出的情况下使用递归,但我通常不会在大多数情况下担心开销。

如果您以递归方式编程,编译器可能会让它对您进行迭代,但您有一个好处,那就是您不必考虑将使用多少空间(因为堆栈是一种神奇的、无限的资源!). 如果您在迭代中使用分段分配处理未知空间问题,那么很可能会浪费与递归一样多的内存,并且可能还会有堆管理CPU开销。另一方面,如果编译器没有修复它,那么递归可能会导致一长串函数返回来展开堆栈。@sh1堆栈绝对不是“神奇的、无限的资源”。事实上,它通常是非常有限的。。。因此,深度递归容易出现“堆栈溢出”错误,通常会突然终止程序…@twalberg我认为如果这不是不言而喻的,那么这个站点将不得不被称为其他站点。我只是在嘲笑这种技术缺乏错误检测(崩溃之外)。也就是说,使用
malloc
也无法检测错误。只要你的程序不崩溃,所有的内存都是神奇的和无限的。Sh1,如果我们想象编译器没有“使”它迭代,那么递归在CPU、堆栈、调用和/或空间方面通常是如何工作的?谢谢你的评论-我只是不太明白。@sh1这种心态有点像“我的银行里有无限的钱,至少在维托带着他的路易斯维尔打手过来之前”。。。记忆不是魔法,也不是无限的,假设它是其中之一,就会导致一些真正可怕的编码实践。更好的方法是准确地了解内存是如何工作的,以及内存的限制是什么,并了解如何在考虑这些限制的情况下正确地编写代码。