networkx.read_edgelist使用的内存比加载的文件多

时间:2018-06-28 14:24:12

标签: python-3.x memory networkx

我有一个3.7 GB的边缘列表文件,它描述了2万个节点上的完整图形,其中每个边缘都有一个浮点数'weight'(全部为1.0)和一个整数'length'(全部为0–1000)。

因此边列表文件的头看起来像这样:

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)])

但是networkx.read_edgelist在运行时,我的计算机因接近100 GB的内存使用而停止运行。

有什么作用?这是read_edgelist特有的,还是networkx.Graph只是 使用大量的内存?不管哪种方式,谁能推荐一个替代的图形库,它以较小的占用空间运行?

1 个答案:

答案 0 :(得分:1)

鉴于讨论从networkx的性能转移到存储“几乎”完整图的最佳方式,我将集中在总结背后的基本原理,而不是使用元组而不是frozenset类型暂时的关键。

我试图对此进行确认,但是给定更多的方法frozenset会比元组占用更多的内存。从this question中,我了解到哈希算法已被重新实现,这有助于执行字典插入和查找(途中需要对键进行哈希处理),但另一方面,Python已针对元组,列表和字符串进行了优化。这么长的长度,这使我想知道是否仅由于这个原因2元组仍不比frozenset快?

现在,当我们考虑NumPy数组时,它们可能会更好地完成任务的原因是多种多样的:

  1. 内存是连续的,这对cache locality有很大帮助(遍历整个数组时的重要事项 数组)。
  2. NumPy对于更大规模的数据(例如成千上万个值),比普通列表更理想。
  3. 个人值的存储效率更高(请参阅下文以获取解释)。

在您的情况下,您似乎需要存储2个值-一个float,一个int。您可以分配2个2-dim ndarray-一种int和一种float32类型。您可以对角填充数组并创建一个特殊的访问器方法(将检查两个索引的顺序,这可能会更慢),也可以填充两个索引(例如:1,2和2,1)。

我假设您并非一直都需要两个值,因此将intfloat32值去耦实际上对于使用各个值的算法性能是有益的。 ndarray所消耗的内存应该较小,并且索引的连续处理要比字典在内存中随机跳动的情况要快得多。