Я пытаюсь вычислить e go -сети для 250k специальных узлов, находящихся в относительно большой сети (8M узлов и 17M ребер). Поскольку процесс резки занимает 3 секунды для каждого специального узла, я решил использовать multiprocessing
:
from graph_tool import Graph, GraphView
from graph_tool.topology import shortest_distance
from graph_tool import load_graph
import multiprocessing
import time
NO_PROC = 4
DEGREE = 4 # neighbours of n-th degree
NO_SPECIAL_NODES = 250000
graph = load_graph('./graph.graphml') #8M nodes, 17M edges
def ego_net(g, ego, n):
print("Graph's identity: {}.".format(id(g))) # check if you use the same object as in other calls
d = shortest_distance(g=g, source=ego, max_dist=n) #O(V+E)
u = GraphView(g, vfilt=d.a < g.num_vertices()) #O(V)
u = Graph(u, prune=True)
return (ego, u)
if __name__ == "__main__":
# generate arguments
data = [(graph, node, DEGREE) for node in range(0, NO_SPECIAL_NODES)]
# choose forking strategy explicitly
ctx = multiprocessing.get_context('fork')
pool = ctx.Pool(NO_PROC)
results = pool.starmap(ego_net, [piece for piece in data])
. Проблема с этим подходом заключается в том, что, хотя я явно выбираю fork
подход , объект graph
не используется подпроцессами, но вместо этого большой объект копируется в каждый из подпроцессов. Этот подход приводит к MemoryError
, так как я не могу предоставить достаточно оперативной памяти для копий graph
.
Я знаю, что структуры данных определены в multiprocessing
, которые поддерживают совместное использование между процессами. Кажется, они не поддерживают сложные объекты, такие как Graph
, экземпляром которого является graph
. Есть ли способ загрузить graph
только один раз и позволить его использовать всем процессам? Я уверен, что функция ego_net
читает из graph
и никак не изменяет объект.