Графический инструмент Python - вычисления e go net с многопроцессорной обработкой - PullRequest
1 голос
/ 30 января 2020

Я пытаюсь вычислить 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 и никак не изменяет объект.

...