【问题标题】:Insufficient Memory behind a finite recursion有限递归背后的内存不足
【发布时间】:2016-05-05 15:44:29
【问题描述】:

我正在做 objsets coursera 作业。我遇到了内存问题

Java 运行时环境的内存不足,无法继续。 本机内存分配 (malloc) 未能分配 253231104 字节用于提交保留内存。

当这样实现联合函数时

def union(that: TweetSet): TweetSet = (left union(right)) union(that) incl(elem)

我通过将 union 方法更改为解决了这个问题

def union(that: TweetSet): TweetSet = right union(left union(that)) incl(elem)

有什么区别?为什么在第一种情况下会出现内存问题?谢谢 !

【问题讨论】:

  • 我想你的问题在这里得到了回答:stackoverflow.com/questions/16217304/…
  • 上面发布的链接只是解释了递归联合的工作原理。我想知道为什么它效率低下以及为什么它以出现内存问题而告终。谢谢!

标签: scala recursion


【解决方案1】:

我也参加了 Coursera 的 Scala FP 课程,遇到了和你一样的问题。我也想出了相同的工作解决方案。了解为什么一个有效而另一个无效的关键在于函数的递归分解。首先,让我们看看您的第一个不终止的解决方案。

def union(that: TweetSet): TweetSet = (left union(right)) union(that) incl(elem)

让我们使用一个简单的示例树和一些任意树that

val tree = NonEmpty(tweet1, NonEmpty(tweet2, Empty, Empty), NonEmpty(tweet3, Empty, Empty))
val that: TweetSet = ...

tree.union(that)

扩展到:

tree.left.union(tree.right)).union(that).incl(tree.elem)

进一步扩展为:

tree.left.left.union(tree.left.right).union(tree.right).incl(tree.left.elem).union(that).incl(tree.elem)

现在我们可以在 Empty TweetSets(tree.left.left 和 tree.left.right)上调用基本案例

tree.right.incl(tree.left.elem).union(that).incl(tree.elem)

到此为止,我们来看看第二种解决方案。

def union(that: TweetSet): TweetSet = left union(right union(that)) incl(elem)


tree.union(that)

扩展到:

tree.left.union(tree.right.union(that)).incl(tree.elem)

再次展开:

tree.left.union(tree.right.left.union(tree.right.right.union(that)).incl(tree.right.elem)).incl(tree.elem)

对 tree.right.left 和 tree.right.right 应用基本情况

tree.left.union(that.incl(tree.right.elem)).incl(tree.elem)

在每个步骤上执行相同数量的步骤后,您可以看到我们有非常不同的表达方式。

解决方案1 ​​= tree.right.incl(tree.left.elem).union(that).incl(tree.elem)

解决方案2 = tree.left.union(that.incl(tree.right.elem)).incl(tree.elem)

在方案一中,可以看到incl调用发生在下一个union的左侧:

tree.right.incl(tree.left.elem).union(that).incl(tree.elem)
           ^^^^

在解决方案 2 中,incl 出现在下一个 union 的右侧。

tree.left.union(that.incl(tree.right.elem)).incl(tree.elem)
                     ^^^^

所以我们可以看到解决方案 1 在联合之前构建了一个全新的树,其元素比上一次迭代少了一个。对于将要处理的树中的每个左分支,此过程将重复。一个 n^2 的效率。创建 n^2 新树时会发生内存分配错误。解决方案 2 使用现有树作为下一个联合的左侧,并从基本情况(n 的效率)返回新树。要与给定的基本情况建立有效的联合,您必须构建 union 表达式的右侧,因为构建左侧会导致工作量成倍增加。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    • 2014-03-24
    • 2012-06-15
    • 2017-03-15
    • 1970-01-01
    • 1970-01-01
    • 2016-08-13
    相关资源
    最近更新 更多