Python 3.x networkx.read\u edgelist使用的内存比它加载的文件多得多
我有一个3.7GB的edgelist文件,描述20k节点上的完整图形,其中每条边都有一个floatPython 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
'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
对于更大范围的数据(比如数万个值),比普通列表更为理想浮点值
,一个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
sfrozenset
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
中,但这可能是不必要的。