Commit 43a159d8 authored by sfritschi's avatar sfritschi
Browse files

Improved performance of algorithm

parent a35a8d6e
......@@ -7,45 +7,6 @@ from netflow import *
import time
import random
import multiprocessing as mp
def process_throat(throat_queue_in, pore_queue_out):
while True:
# Retrieve throat when ready (blocking)
throat = throat_queue_in.get()
# do work
time.sleep(random.random() * 1e-5)
# put result in queue
pore_queue_out.put(throat.pore1)
def process_throats_parallel(network):
n = len(network.pores)
throat_queue_in = mp.Queue() # Throats to be processed
pore_queue_out = mp.Queue() # Throats to remove from network
# Spawn worker threads (only once)
nworkers = 3
workers = []
for tid in range(nworkers):
worker = mp.Process(target=process_throat, args=(throat_queue_in, pore_queue_out), daemon=True)
worker.start()
workers.append(worker)
for i, pore in enumerate(network.pores):
print("Processing pore %d/%d" % (i+1, n))
nresults = len(pore.throats)
while (len(pore.throats) > 0):
throat = pore.throats.pop()
# Put in queue
throat_queue_in.put(throat)
# do work
time.sleep(random.random() * 1e-6)
# Receive results from processes
while (nresults > 0):
pore = pore_queue_out.get()
nresults -= 1
# do work
time.sleep(random.random() * 1e-6)
def main():
basenet = netflow.load_network_from('../netflow/network/network.h5')
......@@ -55,19 +16,7 @@ def main():
print("Min. number of throats per pore: %d" % min([len(pore.throats) for pore in basenet.pores]))
print("Avg. number of throats per pore: %f" % (sum([len(pore.throats) for pore in basenet.pores]) / len(basenet.pores)))
# Modify recursion limit to allow mp.Queue() to pickle recursive
# Throat object
"""
sys.setrecursionlimit(8000)
process_throats_parallel(basenet)
# Verify results
for pore in basenet.pores:
assert(len(pore.throats) == 0)
"""
target = [3, 3, 3]
target = [2, 2, 1]
cutoff = 0.5 * max([basenet.ub[i] - basenet.lb[i] \
for i in range(len(basenet.ub))])
......
gen/plots/dendro.png

135 KB | W: | H:

gen/plots/dendro.png

148 KB | W: | H:

gen/plots/dendro.png
gen/plots/dendro.png
gen/plots/dendro.png
gen/plots/dendro.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -388,7 +388,7 @@ class CellList:
def flatten(self, i: int, j: int, k: int) -> int:
return i + self.nCells[0] * (j + self.nCells[1] * k)
def pore_to_triplet(self, pore) -> List[int]:
def pore_to_triplet(self, pore: Pore) -> List[int]:
from math import floor
return [floor( (pore.pos[i] + self.Lmax) * self.invCellSizes[i]) \
for i in range(self.dim)]
......@@ -421,7 +421,7 @@ class CellList:
# Compute cell index of each pore and add it to respective set
def sort_pores(self, pores: Set[Pore]) -> List[Set]:
# DEBUG
# DEBUG (Statistics)
"""
cellCounts = [0] * self.totalCells
for pore in pores:
......@@ -444,7 +444,7 @@ class CellList:
cellIdx = self.pore_to_index(pore)
poresSorted[cellIdx].add(pore)
"""
# DEBUG
# DEBUG (Verification)
for i in range(self.totalCells):
for pore in poresSorted[i]:
cellIdx = self.pore_to_index(pore)
......@@ -615,35 +615,22 @@ def generate_dendrogram(basenet: Network, targetsize: List[int], \
for i, pore in enumerate(pores[:n]):
# (re)run triangulation if maximal number of neighbors exceeds
# threshold given by 2x init. maximum (large nnbrs -> expensive search)
"""
if ((i == 0) or (nnbrs > 2*nnbrs0)):
if (not mute): print(" triangulation", end="", flush=True)
import scipy.spatial.qhull as qh
try:
neighborhood = triangulation(pores)
nnbrs = max([len(nl) for nl in neighborhood.values()])
except qh.QhullError as err:
print("Error: triangulation failed,", err)
if (i == 0): raise
if (not mute): print("\b"*14 + " "*14 + "\b"*14, end="", flush=True)
"""
# check throats and neighborhood
if (not mute):
print("\b"*24 + f"pore {i:7d}" + " "*12, end="", flush=True)
if (len(pore.throats) == 0): continue # no further connection needed
"""
if neighborhood == {}: break # no pores left to connect to
if (i == 0): nnbrs0 = nnbrs
# lists with front and candidate pores
front = neighborhood[pore]
front = dict(zip(front,
[distance(pore.pos, nbor.pos) for nbor in front]))
candidates = {p:l for p, l in front.items()} # copy front dict
"""
neighborhood = cellList.nbor_indices(pore)
conpores = set() # pores that pore is connected to
# find candidates in neighborhood and respective throat lengths
candidates = {}
for idx in neighborhood:
for nbor in poresSorted[idx]:
if (nbor == pore): continue
l = distance(pore.pos, nbor.pos)
if (l < basenet.Lmax):
candidates[nbor] = l
# establish throat connections between pore and best candidate
while (len(pore.throats) > 0):
if (not mute):
print("\b"*12 + ", throat {0:3d}".format(len(pore.throats)),
......@@ -651,37 +638,17 @@ def generate_dendrogram(basenet: Network, targetsize: List[int], \
throat = pore.throats.pop()
lt = distance(*throat_ends(throat,
[ub-lb for lb,ub in zip(basenet.lb,basenet.ub)])) # target len.
"""
# gather candidates
while (len(front) > 0):
if (min(front.values()) >= lt): break
# grow search region with candidates
newfront = {}
for frontpore in front:
for nbor in neighborhood[frontpore]:
if (nbor == pore): continue # no self connections
l = distance(pore.pos, nbor.pos)
# distinguish between new front-/candidate-pores
if (not nbor in candidates): newfront[nbor] = l
candidates[nbor] = l
front = {p:l for p, l in newfront.items()} # copy
"""
# find best candidate
# avoid double connections and throats longer than Lmax
candidates = {}
for idx in neighborhood:
for nbor in poresSorted[idx]:
if (nbor == pore): continue
l = distance(pore.pos, nbor.pos)
candidates[nbor] = l
# PROBLEM: pore in poresSorted should not have 0 throats -> inconsistent state
# TODO: Search neighboring cells in parallel
# TODO: Replace sort with linear search operation
ranking = [(l,p) for p, l in candidates.items() \
if (not p in conpores) and (l < basenet.Lmax)]
if (not p in conpores)]
if (len(ranking) == 0):
k = k+1; continue # no candidates left, give up
ranking.sort(key=lambda lp: abs(lp[0]-lt))
nbor = ranking[0][1] # pore
nborc = nbor # memorize potential periodic copy
# find original of buffer layer pore
if (nbor.label != LABELS[0]):
......@@ -701,23 +668,21 @@ def generate_dendrogram(basenet: Network, targetsize: List[int], \
nbor.throats.remove(ranking[0][1])
# remove fully connected nbor from search neighborhood
if (len(nbor.throats) == 0):
# remove fully-connected nbor pore from candidates
del candidates[nborc]
nborIdx = cellList.pore_to_index(nbor)
poresSorted[nborIdx].remove(nbor)
#nnbrs = expel(pore, nbor, neighborhood, front, candidates, nnbrs)
for cpore in copies[nbor]:
cnborIdx = cellList.pore_to_index(cpore)
poresSorted[cnborIdx].remove(cpore)
#nnbrs = expel(pore, cpore, neighborhood, front, candidates, nnbrs)
# remove fully connected pore from search neighborhood
poreIdx = cellList.pore_to_index(pore)
poresSorted[poreIdx].remove(pore)
#nnbrs = expel(pore, pore, neighborhood, front, candidates, nnbrs)
for cpore in copies[pore]:
cporeIdx = cellList.pore_to_index(cpore)
poresSorted[cporeIdx].remove(cpore)
#nnbrs = expel(pore, cpore, neighborhood, front, candidates, nnbrs)
print("\b"*24 + "{0:d} throats in total, {1:d} unrealised".\
format(len(throats), k))
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment