Как упростить (или распараллелить с многопроцессорной обработкой) некоторый код Python 3.2 с большим количеством циклов? - PullRequest
1 голос
/ 10 сентября 2011

Я пытался научить себя оптимизировать python и, возможно, распараллелить мою проблему. Ссылки, которые я использовал, перечислены в моем вопросе на http://www.python -forum.org / pythonforum / viewtopic.php? F = 18 & t = 28855

Однако мое приложение, основанное на модуле networkx, по-прежнему очень плохо масштабируется с размером сети, что, я думаю, является в основном ошибкой моих петель, а не специфичной для networkx. Имея небольшой опыт и сосредоточенность на выполнении этой единственной работы, я был бы очень признателен, если бы вы могли просмотреть мой код и точно определить, как вместо этого должны быть сформулированы циклы или какой-то другой прием. Подойдет любой краткий комментарий, я постараюсь взять его оттуда.

Вот ключевые и грязные вещи, которые, как я ожидаю, станут узкими местами:

Эта часть проецирует двудольный граф двудольного (двудольного) графа в соседа по клетке.

# Dictionary for edge attributes in projected graph:
# 0: overlap_length
# 1: overlap_start
# 2: overlap_end
# 3: cell
# 4: level

def time_overlap_projected_graph_parallel(B, nodes):
    G=nx.MultiGraph()
    G.add_nodes_from((n,B.node[n]) for n in nodes)
    for u in nodes:
        unbrs = set(B[u])
        nbrs2 = set((n for nbr in unbrs for n in B[nbr])) - set([u])
        for v in nbrs2:
            for mutual_cell in set(B[u]) & set(B[v]):
                for uspell in B.get_edge_data(u,mutual_cell).values():
                    ustart = uspell[1]
                    uend = uspell[2]
                    for vspell in B.get_edge_data(v,mutual_cell).values():
                        vstart = vspell[1]
                        vend = vspell[2]
                        if uend > vstart and vend > ustart:
                            ostart = max(ustart,vstart)
                            oend = min(uend,vend)
                            olen = (oend-ostart+1)/86400
                            ocell = mutual_cell
                            if (v not in G[u] or ostart not in [ edict[1] for edict in G[u][v].values() ]):
                                G.add_edges_from([(u,v,{0: olen,1: ostart,2: oend,3: ocell})])
    return G

Эта часть проясняет предыдущий результат путем объединения нескольких связей (заклинаний в одной ячейке) между одними и теми же людьми.

# Dictionary for edge attributes in consolidated graph:
# 5: total_overlap
# 6: first_overlap
# 7: last_overlap
# 8: cell_list
# 9: spell_list

def consolidated_g_parallel(B):
    G = nx.Graph()
    G.add_nodes_from(B)
    for n in B.nodes_iter():
        for m in B.neighbors_iter(n):
            omin = 2000000000.0
            omax = 0.0
            otot = 0.0
            cells = []
            spells = []
            for ed in B.get_edge_data(m,n).values():
                omin = min(omin,ed[1])
                omax = max(omax,ed[2])
                otot += ed[0]
                cells.append(ed[3])
                spells.append((ed[1],ed[2]))
            G.add_edges_from([(n,m,{5: otot,6: omin,7: omax,8: cells,9: spells})])
    return G

При этом создается новый граф, в котором все ссылки более высокого порядка (скажем, сокамерники по соседству, по крайней мере, до порядка, установленного параметром) предыдущего результата становятся прямыми ссылками, которые требуют некоторой грубой работы из-за важная хронология ссылок.

def consolidated_mdg_parallel(B):
    print('number of self-loops',B.number_of_selfloops())
    G = B.to_directed()
    for u,v,d in G.edges(data=True):
        d[4]=1
    for n in G.nodes_iter():
        sinks = nx.algorithms.boundary.node_boundary(B,[n])
        nsink = list(sinks)
        nsink.append(n)
        sources = nx.algorithms.boundary.node_boundary(B,nsink)
        while len(sinks) > 0 and len(sources) > 0 :
            for u in sources:
                for v in nx.algorithms.boundary.node_boundary(B,[u],sinks):
                    for edata in G[u][v].values():
                        for ed in G[v][n].values():
                            if edata[1] <= ed[2]:
                                oend = min(edata[2],ed[2])
                                ostart = max(edata[1],ed[1])
                                otot = min(ed[0],edata[0])
                                lvl = edata[4] + 1
                                G.add_edges_from([(u,n,{0: otot,1: ostart,2: oend,3: {},4: lvl})])
            nsink.extend(sources)
            sinks = list(set(sources)&set(G.predecessors(n)))
            sources = nx.algorithms.boundary.node_boundary(B,nsink)
    H = nx.MultiDiGraph()
    for n in G.nodes_iter():
        for m in G.neighbors_iter(n):
            omin = 2000000000.0
            omax = 0.0
            otot = 0.0
            for lvl in range(1,maxorder):
                for ed in G.get_edge_data(n,m).values():
                    if ed[4] == lvl:
                        otot += ed[0]
                if otot > 0:
                    H.add_edges_from([(n,m,{0: otot,4: lvl})])
                otot = 0.0
#                               print('Higher-order link added!')
    return H

Эта часть (конечно, не функция) записывает отдельные текстовые файлы для каждого из возможных порядков ссылок с перечисленными краями.

empty = ['nothing']
for i in range(1,maxorder):
    empty.append(set(J.nodes()))

# Write simple adjacency representation for spmat --- note losing track of length of spells and chronology!
for i in range(1,maxorder):
    targets[i].write('0 '+str(J.number_of_nodes())+' SHAPE KEY')

for e in J.edges_iter(data=True):
# (u,n,{0: otot,1: ostart,2: oend,3: {},4: lvl})
        print(e)
        if e[2][4] < maxorder:
            targets[e[2][4]].write('\n{} {} {}'.format(str(e[1]),str(e[0]),str(1/e[2][0])))
            try:
                empty[e[2][4]].remove(e[1])
            except:
                pass
for i in range(1,maxorder):
    for n in list(empty[i]):
        targets[i].write('\n'+str(n))
    targets[i].close()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...