Python 3.x networkx.read\u edgelist使用的内存比它加载的文件多得多

Python 3.x networkx.read\u edgelist使用的内存比它加载的文件多得多,python-3.x,memory,networkx,Python 3.x,Memory,Networkx,我有一个3.7GB的edgelist文件,描述20k节点上的完整图形,其中每条边都有一个float'weight'(全部为1.0)和一个int'length'(全部为0-1000) 因此edgelist文件的头部如下所示: 0 1 1.0 76 0 2 1.0 85 0 3 1.0 118 0 4 1.0 94 0 5 1.0 71 ... 我正在使用以下方式加载它: def load_graph(file_path: str) -> Graph: return read_edg

我有一个3.7GB的edgelist文件,描述20k节点上的完整图形,其中每条边都有一个float
'weight'
(全部为1.0)和一个int
'length'
(全部为0-1000)

因此edgelist文件的头部如下所示:

0 1 1.0 76
0 2 1.0 85
0 3 1.0 118
0 4 1.0 94
0 5 1.0 71
...
我正在使用以下方式加载它:

def load_graph(file_path: str) -> Graph:
    return read_edgelist(file_path, nodetype=int,
                         data=[('weight', float),
                               ('length', int)])
但在运行的过程中,我的电脑因近100GB的内存使用而停止运行

有什么好处?这是
read\u edgelist
特有的,还是
networkx.Graph
只是
使用大量内存?无论采用哪种方式,有人能推荐一种占地面积较小的图形库吗?

鉴于对networkx性能的讨论与存储“几乎”的最佳方式不同完整图我将集中于总结字典键背后的基本原理,而不是使用元组而不是
frozenset
type

我试图找到一个确认的方法,但给出稍微多一点的方法
frozenset
可能比tuple占用更多的内存。从中我了解到,哈希算法已经重新实现,这有助于提高字典插入和查找的性能(在执行过程中需要对键进行哈希),但另一方面Python对元组、列表、,还有各种长度的字符串,这让我想知道2元组是否仍然比
frozenset
快,如果仅仅出于这个原因

现在,当我们考虑<代码> NoMPy < /Cord>数组时,它们对于任务的原因可能是多方面的:

  • 内存是连续的,这有助于(重要的是)遍历整个内存 数组)
  • NumPy
    对于更大范围的数据(比如数万个值),比普通列表更为理想
  • 单个值的存储效率更高(请参见下面的说明)
  • 在您的情况下,您似乎需要存储2个值—一个
    浮点值
    ,一个
    int
    。您可以分配2个二维
    ndarray
    s-一个
    int
    类型,另一个
    float32
    类型。您可以对角填充数组并创建一个特殊的访问器方法(这将检查索引的两个顺序-这可能会慢一些),或者同时填充两个索引(例如:1,2和2,1)


    我假设您在任何时候都不需要这两个值,因此解耦
    int
    float32
    值实际上有利于使用各自值的算法的性能。
    ndarray
    s消耗的内存应该更小,索引的连续处理速度应该比在内存周围随机跳跃的字典快得多。

    是否有理由需要它成为一个图形
    D[(0,1)]=(1.0,76)
    将是一种更有效的存储边缘的方法。因为它是一个完整的图,所以我不清楚将它存储为一个图,而不仅仅是将它存储为每条边上都有条目的dict有多大优势。这个图给我带来的好处是边是无向的。所以(0,1)和(1,0)是一样的。有没有一种方法可以使用元组(或类似的东西)作为字典键,但不考虑其条目的顺序?这将允许我删除networkx。好的,这个问题的答案是使用
    frozenset
    s作为键,所以我会尝试。另一种方法是使用getter函数,它将始终按照索引的顺序检查元组键(
    frozenset
    有一些开销,使用此数据大小值得优化)。另外,对于处理来说,使用内存更紧凑的存储(例如
    NumPy
    array)对我来说是有意义的。@Sophos谢谢你的评论,但我没有完全明白-你能说得更清楚一点吗?frozenset的开销是多少?我该如何应对?numpy数组会比名元组(我现在使用的是名元组)的冻结键控dict更高效吗?我应该清楚,图表“几乎”完整,但我不能依赖这一事实,例如获取事件边缘列表。现在我使用一个理解集(e代表e在self.edges中,如果n在edge中)其中
    self.edges
    是我提到的格言。我会问一个新的SO问题,但我不确定该问什么@这对你有帮助吗?如果是的话,你能接受这个答案吗?好的,我已经做了很长时间了。最后,就我而言,它似乎是一个从
    tuple
    继承的edge类,效果最好。我认为使用numpy数组在边缘中测试节点成员资格时用处不大(除非我做了一些非常聪明的事情),但我认为
    tuple
    是正确的,而不是
    frozenset
    s
    frozenset
    s只是与元组相比使用了太多的内存。为了防止对其他人有帮助,我制作了
    class Edge(tuple):def uu new_u(self,seq=()):return tuple.\uu new_u(tuple,sorted(seq))
    ,因此
    Edge((0,1))==Edge((1,0))
    真的
    。我还将一个
    断言len(seq)==2
    添加到
    \uuuu new\uuuu
    中,但这可能是不必要的。