【问题标题】:Does divide-and-conquer really win against the increased memory allocation?分而治之真的能战胜增加的内存分配吗?
【发布时间】:2013-07-30 15:50:02
【问题描述】:

我刚刚完成了一些经典的分而治之算法的编码,我提出了以下问题:(更多好奇)

诚然,在很多情况下,分治算法比传统算法更快;例如,在快速傅里叶变换中,它将复杂度从 N^2 提高到 Nlog2N。但是通过编码,我发现,因为“划分”,我们的子问题更多,这意味着我们必须在子问题上创建更多的容器并额外分配更多的内存。想想看,在归并排序中,我们必须在每次递归中创建左右数组,而在快速傅里叶变换中,我们必须在每次递归中创建奇数和偶数数组。这意味着,我们必须在算法期间分配更多内存。

所以,我的问题是,在现实中,例如在 C++ 中,当我们还必须增加内存分配的复杂性时,分而治之的算法真的会赢吗? (或者内存分配根本不需要运行时间,成本为零?)

感谢您帮助我!

【问题讨论】:

  • 在许多情况下,减少函数运行所需的时间需要相应地增加内存使用量。例如,您可以通过在内存中存储许多素数来减少素数查找算法所花费的时间。
  • 在编程中,您经常需要在快速或精简资源之间进行选择,您很少能同时选择两者。 (不幸的是,很容易找到没有选择任何替代方案的程序。)
  • 并不是所有的分治法都需要更多的内存,在很多情况下操作可以就地完成。诚然,在某些情况下需要或需要额外的内存(您可以在合并排序中执行合并步骤而无需获取额外的内存,但性能会更差。
  • 内存分配确实需要一些时间,但是您必须根据具体情况来看待这一点。
  • 复杂性理论中有一些结果可以对某些问题进行权衡。例如,一个重要的结果表明,不能同时在线性时间和对数空间中确定布尔公式的可满足性。您至少需要其中一个,这样做可以减少其他资源的使用。

标签: c++ algorithm memory-management divide-and-conquer


【解决方案1】:

在优化方面,几乎所有事情都是一种资源与另一种资源之间的折衷 - 在传统工程中,它通常是“成本与材料”。

在计算中,通常是“时间与内存使用”的折衷方案。

我认为您的实际问题没有一个简单的答案 - 这实际上取决于算法 - 在现实生活中,这可能会导致妥协的解决方案,即问题被分成更小的部分,但不是全部缩小到最小尺寸,只有“直到它不再有效地划分它”。

内存分配不是零成本操作,如果我们谈论的是newdelete。一旦操作系统用物理内存填充了实际的堆栈内存,堆栈内存的成本几乎为零——在大多数体系结构上最多需要一条额外的指令来在堆栈上腾出一些空间,有时在退出时需要一条额外的指令来返还内存.

真正的答案是,几乎总是在性能方面,对不同的解决方案进行基准测试。

【讨论】:

    【解决方案2】:

    了解在大 O 术语中“提高一级”(例如从 n^2 到 n,或从 n 到 log n)通常很重要,这很有用。考虑一下您的傅立叶示例。

    O(n^2)n=100,你正在查看10000n=1000,你得到一百万,1000000。另一方面,使用O(n*log(n)),您会在n=1009965 中获得664 n=1000。增长放缓应该是显而易见的。

    当然,内存分配会消耗资源,分而治之的一些其他代码也是如此,例如组合各个部分。但整个想法是,额外分配等的开销远远小于小型算法所需的额外时间。

    额外分配的时间通常不是问题,但内存使用本身可以。这是基本的编程权衡之一。您必须在速度和内存使用量之间做出选择。有时您可以负担额外的内存以获得更快的结果,有时您必须保存所有内存。这是许多问题没有“终极算法”的原因之一。比如说,mergesort 很棒,即使在最坏的情况下也可以在O(n * log(n)) 中运行,但它需要额外的内存。除非您使用就地版本,否则运行速度会变慢。或者,也许您知道您的数据可能已经接近排序,然后像 smoothsort 这样的东西更适合您。

    【讨论】:

    • 尽管人们总是需要记住,计算复杂度的渐近界限(大佬和朋友们)不是 n 的函数,它们是 n 的无限函数集。它们隐藏了不占主导地位的常量和因素,掩盖了实现细节,很少用于计算时间,而是一些抽象的“操作”,等等。要比较具有复杂性的两种算法O(f(n))O(g(n)),您不能只取f(n)g(n) 并插入n 的值。有关详细信息,请参阅programmers.stackexchange.com/a/112872/7043
    • @delnan 如果我们讨论的是 big-O 陷阱,请务必记住,O(n) 表示上限,通常也用于表示平均复杂度。对于许多算法来说,区分最佳、最差和平均场景很重要。此外,“不断下降”有时可能会产生误导。 O(n^2) 算法将比 O(n) 更好,O(1000000*n) 对于“小”数据大小 - 有时您的所有数据都是“小”。
    猜你喜欢
    • 2013-01-12
    • 2016-04-04
    • 2013-11-09
    • 2020-07-12
    • 2015-06-23
    • 2013-01-31
    • 1970-01-01
    • 2013-02-02
    • 2023-03-14
    相关资源
    最近更新 更多