【问题标题】:Dijkstra's algorithm: memory consumptionDijkstra 算法:内存消耗
【发布时间】:2012-12-26 11:38:21
【问题描述】:

我有一个 Dijkstra 算法的实现,基于 this website 上的代码。基本上,我有许多节点(比如 10000 个),每个节点可以有 1 到 3 个与其他节点的连接。

节点是在 3d 空间内随机生成的。连接也是随机生成的,但它总是首先尝试找到与其最近邻居的连接,然后慢慢增加搜索半径。每个连接的距离为 1。 (我怀疑这是否重要,但这只是背景)。

在这种情况下,该算法只是用于寻找从起点到所有其他节点的最短跳数。它适用于 10,000 个节点。我遇到的问题是,随着节点数量的增加,比如接近 200 万,我在尝试构建图表时用尽了我所有的计算机内存。

有谁知道实现算法以减少内存占用的替代方法,或者是否有另一种使用更少内存的算法?

【问题讨论】:

  • 由于 Dijkstra 本身与节点数呈线性关系,我想是图形表示本身会消耗大量内存。您使用哪种数据结构来表示图形?
  • 更重要的是,您在哪种架构上运行它?具有几 GB 内存的 PC 应该能够存储超过 2M 的节点,除非每个节点每个都占用数百字节 - 此时您可能需要重新考虑您的节点信息。
  • 您可能在构建图形阶段时出现内存泄漏。你能发布你的代码吗?
  • @emreakyilmaz ,该代码与我第一篇文章中网站中的代码几乎相同。
  • @Mats Petersson:我的电脑有 4 GB 内存!正如 emreaky 所说,可能存在内存泄漏。查看我在问题中发布的链接中的代码,它是否能够处理 200 万个节点的图表?比如long dist[GRAPHSIZE][GRAPHSIZE],200万个节点会不会占用大量内存?

标签: c++ algorithm memory memory-management dijkstra


【解决方案1】:

根据您上面的评论,您用distance matrix long dist[GRAPHSIZE][GRAPHSIZE] 表示图形的边缘。这将占用O(n^2) 内存,这对于n 的大值来说太多了。当您只有少量边时,它在执行时间方面也不是一个很好的表示:它会导致 Dijkstra 的算法在可能更快时花费O(n^2) 时间(其中n 是节点数) ,取决于使用的数据结构。

由于在您的情况下您说每个节​​点最多仅连接到 3 个其他节点,因此您不应使用此矩阵:相反,对于每个节点,您应该存储它所连接的节点的列表。那么当你想遍历一个节点的邻居时,你只需要遍历这个列表。

在某些特定情况下,您甚至不需要存储此列表,因为可以在需要时为每个节点计算它。例如,当图是一个网格并且每个节点都连接到相邻的网格节点时,很容易在运行中找到一个节点的邻居。

【讨论】:

  • Interjay 非常感谢您的回答!感谢其他所有人的贡献。
【解决方案2】:

如果您真的负担不起内存,即使 最小化您的图形表示,您也可以开发一个 Dijkstra 算法的变体,考虑到分而治之的方法。

这个想法是将数据拆分成小块,这样您就可以在每个块中针对其中的每个点执行 Dijkstra 算法。

对于在这些小块中生成的每个解决方案,将其视为另一个数据块的唯一节点,您将从那里开始 Dijkstra 的另一次执行。

例如,考虑以下几点:

.B        .C
                  .E
 .A           .D
       .F                   .G

您可以选择距离给定节点最近的点,例如,在两跳内,然后将解作为扩展图的一部分,将前面的点视为仅一组点,距离等于结果Dijkstra 解的距离。

假设你从D开始:

  • 在给定的number of hops 中选择closest pointsD
  • 对所选条目使用 Dijkstra 算法,从 D 开始;
  • 将解决方案用作图,其中中心节点D 和最短路径中的最后一个节点作为直接链接到D 的节点;
  • 扩展图,重复算法,直到所有节点都被考虑在内。

虽然这里有昂贵的额外处理,但您可以超越内存限制,如果您有其他机器,您甚至可以分发进程。

请注意,这只是流程的想法,我描述的流程不一定是最好的方法。在寻找分布式 Dijkstra 算法时,您可能会发现一些有趣的东西。

【讨论】:

  • 嗨鲁本斯,感谢您的回答。分而治之听起来是最终的好方法。我将首先尝试 interjay 的建议,因为它目前适合我的节点的生成方式和连接的存储方式(节点数组,每个节点都包含一个连接节点列表)。也许如果在那里达到限制,我可以继续你的方法。谢谢!
  • @John 很高兴您找到了一个不需要对您已有的内容进行太多更改的建议;如果发生这种情况,达到了限制,我很乐意提供帮助!祝你好运!
【解决方案3】:

我非常喜欢 boost::graph。它的内存消耗非常可观(我在具有 1000 万个节点和 2Gb 内存的道路网络上使用过它)。

它有一个 Dijkstra 实现,但如果目标是自己实现和理解它,您仍然可以使用他们的图形表示(我建议邻接表)并将您的结果与他们的结果进行比较,以确保您的结果是正确的。

有些人提到了其他算法。我认为这不会对内存使用产生很大影响,但更有可能影响速度。 2M节点,如果拓扑接近街道网络,从一个节点到所有其他节点的运行时间将不到一秒。

http://www.boost.org/doc/libs/1_52_0/libs/graph/doc/index.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-21
    • 2010-10-12
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 2011-10-03
    • 2012-11-24
    相关资源
    最近更新 更多