我正在开发一个应用程序,其中我需要一个结构来表示内存中的一个巨大的图形(在1000000到6000000个节点和每个节点100或600个边缘之间)。边表示将包含关系的一些属性。
我尝试过内存映射表示,数组,字典和字符串来表示内存中的结构,但由于内存限制,这些结构总会崩溃。
我想得到一个建议,我可以代表这个或类似的东西。
顺便说一下,我正在使用python。
答案 0 :(得分:14)
如果您在内存中需要它的唯一原因是因为您需要能够快速读取和写入它,那么请使用数据库。数据库的读写速度非常快,通常它们可以在不进入磁盘的情况下读取。
答案 1 :(得分:6)
根据您的硬件资源,对于图表这样大小的内存全部可能是不可能的。从图形特定的DB角度来看,有两种可能的选择:
由于你使用Python,你看过Networkx吗?如果你感兴趣的话,你在多大程度上加载了这个尺寸的图表?
答案 2 :(得分:3)
考虑到节点数量,您似乎只有很少的边缘 - 这表明大多数节点并不是绝对必要的。那么,为什么不使用稀疏结构而只是在使用时插入它们,而不是实际存储所有节点?这应该很容易用字典做;只是在将节点用作边缘之前不要插入节点。
可以使用节点上的adjacency list存储边缘。
当然,这仅适用于总共100-600个节点的情况。如果你的意思是每个节点,这是一个完全不同的故事。
答案 3 :(得分:3)
我怀疑你是否能够使用内存结构,除非你有大量的内存供你使用:
假设您正在讨论来自每个节点的600个有向边,其中一个节点是4字节(整数密钥),并且有向边是JUST目标节点密钥(每个4字节)。
然后每个节点的原始数据是4 + 600 * 4 = 2404字节x 6,000,000 =超过14.4GB
节点(或边缘)没有任何其他开销或任何其他数据。
答案 4 :(得分:2)
scipy.sparse.csgraph包可能能够处理这个问题 - 500万个节点*平均100个边缘是5亿个对,每对8个字节(两个整数ID)只有4GB左右。我认为csgraph
使用压缩因此它将使用更少的内存;这可能适用于您的笔记本电脑。
csgraph没有与networkx一样多的功能,但它使用的是更少的内存。
答案 5 :(得分:1)
假设你的每个节点意味着600,你可以尝试这样的事情:
import os.path
import cPickle
class LazyGraph:
def __init__(self,folder):
self.folder = folder
def get_node(self,id):
f = open(os.path.join(self.folder,str(id)),'rb')
node = cPickle.load(f)
f.close() # just being paranoid
return node
def set_node(self,id,node):
f = open(os.path.join(self.folder,str(id)),'wb')
cPickle.dump(node,f,-1) # use highest protocol
f.close() # just being paranoid
使用数组(或numpy数组)来保存实际的节点ID,因为它们更快。
请注意,这将非常慢。
你可以使用线程来预取节点(假设你知道你正在处理它们的顺序),但它不会很有趣。
答案 6 :(得分:0)
听起来你需要一个数据库和一个结果的迭代器。然后你不必同时将它全部保存在内存中,但你总是可以访问它。
答案 7 :(得分:0)
如果您决定使用某种数据库,我建议查看neo4j及其python绑定。它是一个能够处理大型图形的图形数据库。这是今年PyCon的presentation。