Обновление атрибутов ребер большого плотного графа

#graph #networkx

#График #networkx

Вопрос:

У меня есть большой и плотный граф, атрибуты ребер которого обновляются с помощью следующего кода. Вкратце, я устанавливаю атрибуты ребер на основе некоторых вычислений значений, извлеченных из других словарей (degdict, pifeadict, nodeneidict и т.д.). Мой самый маленький график имеет 15 миллионов ребер. Когда выполнение достигает этой стадии, загрузка процессора падает до 10%, а объем памяти увеличивается до 69%. Для больших графиков мой процесс останавливается из-за использования памяти на 90%. Я не уверен, где что-то идет не так.

В дополнение к устранению этой проблемы с памятью, мне также нужно ускорить этот цикл, если это возможно — возможно, параллельное решение для обновления атрибутов границ. Пожалуйста, предложите решения.

     for fauth, sauth in Gcparam.edges_iter():
        first_deg = degdict[fauth]
        sec_deg = degdict[sauth]
        paval = float(first_deg*sec_deg)/float(currmaxdeg * 
                                                         currmaxdeg)
        try:
            f2 = dmpdict[first_deg][sec_deg]
        except KeyError:
            f2 = 0.0
        try:
            pival = pifeadict[first_deg][sec_deg]
        except KeyError:
            pival = 0.0
        delDval = float(abs(first_deg - sec_deg))/(float(currmaxdeg)*delT)
        f5 = calc_comm_kws(fauth, sauth, kwsdict)
        avg_ndeg = getAvgNeiDeg(fauth, sauth, nodeneidict, currmaxdeg)/delT
        prop = getPropensity(fauth, sauth, nodeneidict, currmaxdeg, Gparam)/delT
        tempdict = {'years':[year], 'pa':[paval],
                        'dmp':[f2], 'pi':[pival], 'deld':[delDval],
                        'delndeg':[avg_ndeg], 'delprop' :[prop],
                        'ck' :[f5]
                       }
        Gcparam[fauth][sauth].update(tempdict)
  

Комментарии:

1. Хранение 15 миллионов словарей, таких как ваш «tempdict», — это проблема с памятью. Вы можете попробовать уменьшить объем данных, которые вы там храните. Нужно ли вам хранить список для каждого значения dict? Например. можете ли вы использовать ‘years’:year вместо ‘years’: [year] .

2. @Aric: типичные данные атрибута для ребра выглядят следующим образом: {‘years’:[t1 t2 t3], ‘attr1’: [x y z], ‘attr2’: [a b c]}. Так что, да, мне нужно иметь [год] по мере накопления данных из растущего графика.

3. @Aric: я сохраняю 15-миллиметровые дикты по одному для каждого ребра. Вы предполагаете, что хранение сложных объектов python в качестве атрибутов границ неэффективно для памяти?

Ответ №1:

Вы можете оценить объем хранилища, необходимый для данных на каждом ребре, следующим образом:

 In [1]: from pympler.asizeof import asizeof

In [2]: tempdict = {'years':[1900], 'pa':[1.0],
                        'dmp':[2.0], 'pi':[3.0], 'deld':[7],
                        'delndeg':[3.4], 'delprop' :[7.5],
                        'ck' :[22.0]
}

In [3]: asizeof(tempdict)
Out[3]: 1000
  

Похоже, что 1000 байт — это нижняя граница того, что вы делаете. Умножьте это на общее количество ребер.
NetworkX также имеет некоторые накладные расходы для структур данных узлов и ребер, которые зависят от того, какой тип объекта вы используете для узлов. Целые числа являются наименьшими.

Комментарии:

1. спасибо за представление pympler. Похоже, мне нужно искать другие парадигмы программирования — у меня просто нет 15 ГБ памяти. Кстати, мои узлы — это строки. Или, возможно, мне следует рассмотреть возможность создания массивов numpy в качестве атрибутов границ. Возможно ли это?

2. Итак, я могу добавить массив numpy в качестве атрибута edge, однако простой массив numpy занимает всего 80 байт, а в виде атрибута edge он занимает 408 байт, что по-прежнему меньше 1000.