如果我有足够的RAM,如何加速大型物体的拆除?

时间:2010-05-04 15:31:49

标签: python serialization pickle

使用cPickle(将其作为二进制pickle文件存储在磁盘上时为1 GB),需要一个小时才能读取1 GB的NetworkX图形数据结构。

请注意,文件会快速加载到内存中。换句话说,如果我跑:

import cPickle as pickle

f = open("bigNetworkXGraph.pickle","rb")
binary_data = f.read() # This part doesn't take long
graph = pickle.loads(binary_data) # This takes ages

如何加快上次操作?

请注意,我尝试使用两种二进制协议(1和2)来腌制数据,并且我使用哪种协议似乎没有太大区别。另请注意,虽然我使用上面的“装载”(意思是“加载字符串”)函数,但它正在加载二进制数据,而不是ascii-data。

我正在使用的系统上有128GB的RAM,所以我希望有人会告诉我如何增加一些隐藏在pickle实现中的读缓冲区。

8 个答案:

答案 0 :(得分:8)

我在使用cPickle本身读取~750 MB igraph数据结构(二进制pickle文件)方面取得了巨大成功。这是通过简单地完成提到here

的pickle加载调用来实现的

您案例中的示例代码段如下:

import cPickle as pickle
import gc

f = open("bigNetworkXGraph.pickle", "rb")

# disable garbage collector
gc.disable()

graph = pickle.load(f)

# enable garbage collector again
gc.enable()
f.close()

这绝对不是最合适的方式,但是,它大大减少了所需的时间 (对我来说,它从843.04s减少到41.28s,大约20x)

答案 1 :(得分:6)

您可能受到Python对象创建/分配开销的约束,而不是本身的unpickling。 如果是这样的话,除了没有创建所有对象之外,你几乎无法加快速度。你一次需要整个结构吗?如果没有,您可以使用数据结构的延迟填充(例如:通过pickle字符串表示结构的一部分,然后仅在访问它们时将其解开)。

答案 2 :(得分:4)

为什么不尝试marshaling您的数据并使用memcached(例如)将其存储在RAM中。是的,它有一些限制但是this指出编组比酸洗更快(20到30倍)。

当然,您还应该花费尽可能多的时间来优化数据结构,以便最大限度地减少要存储的数据的数量和复杂性。

答案 3 :(得分:1)

这太荒谬了。

我有一个巨大的~150MB字典(实际上collections.Counter),我正在使用二进制格式的cPickle进行读写。

写作花了大约3分钟 我在16分钟时停止阅读,我的RAM完全被阻塞了。

我现在正在使用元帅,它需要: 写:~3s
阅读:~5s

我戳了一下,发现了article 猜猜我从来没有看过泡菜来源,但是它构建了一个完整的VM来重建字典? 在IMHO文档中应该有关于非常大的对象的性能的说明。

答案 4 :(得分:1)

我也试图加快网络图的加载/存储。我使用adjacency_graph方法将图表转换为可序列化的内容,例如请参阅此代码:

.class

但是,这种from networkx.generators import fast_gnp_random_graph from networkx.readwrite import json_graph G = fast_gnp_random_graph(4000, 0.7) with open('/tmp/graph.pickle', 'wb+') as f: data = json_graph.adjacency_data(G) pickle.dump(data, f) with open('/tmp/graph.pickle', 'rb') as f: d = pickle.load(f) H = json_graph.adjacency_graph(d) 转换方法非常慢,因此在转换时获得的时间可能会在转换时丢失。

所以这实际上并没有加快速度,让人失望。运行此代码可提供以下时间:

adjacency_graph

这种指数增长可能是由于图表的边缘越来越多。这是一个测试要点,如果你想尝试自己

https://gist.github.com/wires/5918834712a64297d7d1

答案 5 :(得分:0)

你可以做的最好的事情就是把大数据分成最小的对象,比如说小于50MB,所以可以存储在ram中,并重新组合它。

Afaik没有办法通过pickle模块自动拆分数据,所以你必须自己做。

无论如何,另一种方式(更难)是使用NoSQL Database之类的MongoDB来存储您的数据...

答案 6 :(得分:0)

一般来说,我发现如果可能的话,在python中将大对象保存到磁盘时,使用numpy ndarrays或scipy.sparse矩阵会更有效。

因此,对于像示例中的巨大图形,我可以将图形转换为scipy稀疏矩阵(networkx具有执行此操作的功能,并且编写一个并不困难),然后将该稀疏矩阵保存为二进制格式。

答案 7 :(得分:-4)

为什么不使用pickle.load

f = open('fname', 'rb')
graph = pickle.load(f)