Python多进程内存不足:分批写入磁盘及NetworkX存储优化问询
解决方案:并行计算内存耗尽与NetworkX存储优化
一、分批写入磁盘方案完全可行
你的核心问题是p.map会将15000个大型NetworkX图对象一次性存放在内存的results_list中,直接撑爆内存。分批处理+逐批写入磁盘的思路能从根源上解决这个问题:每批计算完成后立即将结果写入磁盘,释放当前批次占用的内存,再处理下一批次。
具体实现代码
import multiprocessing from functools import partial import pickle import networkx as nx def some_func(a): # 实际生成带属性的NetworkX图逻辑 G = nx.Graph() G.add_node(a, node_id=a, attr_example="some_value") # 省略其他图构建代码... return G def process_batch(batch, output_path): with multiprocessing.Pool() as p: batch_results = p.map(partial(some_func), batch) # 逐批追加写入到文件 with open(output_path, "ab") as f: for graph in batch_results: pickle.dump(graph, f) # 配置参数 a_list_of_a = list(range(15000)) # 你的15000个节点编号列表 batch_size = 100 # 根据内存调整,64GB内存可尝试200-500 output_file = "results/final_data.pkl" # 初始化清空文件 open(output_file, "wb").close() # 分批处理 for idx in range(0, len(a_list_of_a), batch_size): current_batch = a_list_of_a[idx:idx+batch_size] print(f"处理批次 {idx//batch_size + 1} / {(len(a_list_of_a)+batch_size-1)//batch_size}") process_batch(current_batch, output_file) # 读取结果的方式(按需加载) # def load_all_graphs(file_path): # graphs = [] # with open(file_path, "rb") as f: # while True: # try: # graphs.append(pickle.load(f)) # except EOFError: # break # return graphs
二、NetworkX图的更优存储方式
针对大型带属性图的存储,普通pickle不是最优选择,结合以下方式能进一步降低内存和磁盘占用:
- 单个图独立存储:不要将所有图打包成一个列表,而是给每个图单独生成文件(比如
results/graph_{node_id}.gpickle),使用nx.write_gpickle(G, filename)写入。这样处理时内存仅需承载单个图,读取时可按需加载特定节点的图,无需一次性加载全部。 - 使用NetworkX专属序列化格式:
gpickle是NetworkX针对图结构优化的pickle变体,比普通pickle序列化/反序列化速度更快,内存占用更低,且能完整保留节点、边的所有属性。 - 压缩存储:结合gzip压缩写入,进一步减少磁盘占用,同时读取时也能降低内存峰值:
import gzip with gzip.open(f"results/graph_{a}.gpickle.gz", "wb") as f: nx.write_gpickle(G, f) - 提取共享数据:如果多个图存在重复的结构或属性(比如公共边、通用属性),可将这部分单独存储为公共文件,每个图仅保存差异部分,大幅减少冗余数据。
内容的提问来源于stack exchange,提问作者Xudong
相关产品推荐
相关产品推荐

