Commit e5559ad5 authored by sfritschi's avatar sfritschi
Browse files

Added python multiprocessing examples

parent 792aa67b
from time import perf_counter
import multiprocessing as mp
def addToList(myArr, tid, displs, loads):
start = displs[tid]
end = start + loads[tid]
for i in range(start, end):
myArr[i] = i
def addToListSerial(myArr, n):
for i in range(n):
myArr[i] = i
def main():
nThreads = 4
#n = 1 << 20 # approx. 10^6
n = 20000000
load = n // nThreads
remain = n % nThreads
loads = [load for _ in range(nThreads)]
for i in range(remain):
loads[i] += 1
cSum = 0
displs = loads.copy()
for i in range(nThreads):
temp = displs[i]
displs[i] = cSum
cSum += temp
myArr = mp.RawArray("i", n)
myArrSeq = [0 for _ in range(n)]
jobs = []
start = perf_counter()
for tid in range(nThreads):
load = loads[tid]
proc = mp.Process(target=addToList, args=(myArr, tid, displs, loads))
proc.start()
jobs.append(proc)
for job in jobs:
job.join()
end = perf_counter()
durParallel = end - start
start = perf_counter()
addToListSerial(myArrSeq, n)
end = perf_counter()
durSeq = end - start
print("Time parallel: %e s" % durParallel)
print("Time sequential: %e s" % durSeq)
print("Speedup: %e" % (durSeq / durParallel))
correct = True
for i in range(n):
if myArr[i] != myArrSeq[i]:
correct = False
if correct:
print("Correct!")
else:
print("False!")
if __name__ == '__main__':
main()
from time import perf_counter
import multiprocessing as mp
def addToList(myList, tid, displs, loads):
start = displs[tid]
end = start + loads[tid]
for i in range(start, end):
myList.append(i)
def addToListSerial(myList, n):
for i in range(n):
myList.append(i)
def main():
nThreads = 4
#n = 1 << 20 # approx. 10^6
n = 2000
load = n // nThreads
remain = n % nThreads
loads = [load for _ in range(nThreads)]
for i in range(remain):
loads[i] += 1
cSum = 0
displs = loads.copy()
for i in range(nThreads):
temp = displs[i]
displs[i] = cSum
cSum += temp
myList = mp.Manager().list()
myListSeq = []
jobs = []
start = perf_counter()
for tid in range(nThreads):
load = loads[tid]
proc = mp.Process(target=addToList, args=(myList, tid, displs, loads))
proc.start()
jobs.append(proc)
for job in jobs:
job.join()
end = perf_counter()
durParallel = end - start
myList.sort() # sort list for sanity check
start = perf_counter()
addToListSerial(myListSeq, n)
end = perf_counter()
durSeq = end - start
print("Time parallel: %e s" % durParallel)
print("Time sequential: %e s" % durSeq)
print("Speedup: %e" % (durSeq / durParallel))
correct = True
for i in range(n):
if myList[i] != myListSeq[i]:
correct = False
if correct:
print("Correct!")
else:
print("False!")
if __name__ == '__main__':
main()
import multiprocessing as mp
def addToList(myList, val):
myList.append(val)
def main():
nThreads = 4
myList = mp.Manager().list()
jobs = []
for tid in range(nThreads):
proc = mp.Process(target=addToList, args=(myList, tid))
proc.start()
jobs.append(proc)
for job in jobs:
job.join()
print(myList)
if __name__ == '__main__':
main()
...@@ -507,6 +507,9 @@ def generate_dendrogram(basenet: Network, targetsize: List[int], \ ...@@ -507,6 +507,9 @@ def generate_dendrogram(basenet: Network, targetsize: List[int], \
del(neighborhood[outsider]) del(neighborhood[outsider])
return nnbrs return nnbrs
"""
PARALELLIZATION START
"""
# throats, connect pores # throats, connect pores
if (not mute): print("\b"*21 + "connecting") if (not mute): print("\b"*21 + "connecting")
throats = [] throats = []
...@@ -592,6 +595,9 @@ def generate_dendrogram(basenet: Network, targetsize: List[int], \ ...@@ -592,6 +595,9 @@ def generate_dendrogram(basenet: Network, targetsize: List[int], \
nnbrs = expel(pore, pore, neighborhood, front, candidates, nnbrs) nnbrs = expel(pore, pore, neighborhood, front, candidates, nnbrs)
for cpore in copies[pore]: for cpore in copies[pore]:
nnbrs = expel(pore, cpore, neighborhood, front, candidates, nnbrs) nnbrs = expel(pore, cpore, neighborhood, front, candidates, nnbrs)
"""
PARALELLIZATION END
"""
print("\b"*24 + "{0:d} throats in total, {1:d} unrealised".\ print("\b"*24 + "{0:d} throats in total, {1:d} unrealised".\
format(len(throats), k)) format(len(throats), k))
......
This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019/Debian) (preloaded format=pdflatex 2021.4.27) 21 OCT 2021 17:58 This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019/Debian) (preloaded format=pdflatex 2021.4.27) 21 OCT 2021 21:22
entering extended mode entering extended mode
restricted \write18 enabled. restricted \write18 enabled.
%&-line parsing enabled. %&-line parsing enabled.
......
No preview for this file type
No preview for this file type
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
\subsection{Solver} \subsection{Solver}
\hspace{0.5cm}The actual solver written in C then utilizes PETSc's collection of krylov-subspace (KSP) methods to iteratively approximate the solution of the system in parallel with the available MPI processes. To avoid data duplication, the initial assembly of PETSc objects is only done on the root rank and then communicated in parts to the corresponding ranks through PETSc's collective \verb|Assembly| routines. The iterative method chosen to solve the non-symmetric pressure system, arising from the flow network, is GMRES together with a left algebraic multi-grid preconditioner supplied via hypre \cite{hypre-web-page}. \hspace{0.5cm}The actual solver written in C then utilizes PETSc's collection of krylov-subspace (KSP) methods to iteratively approximate the solution of the system in parallel with the available MPI processes. To avoid data duplication, the initial assembly of PETSc objects is only done on the root rank and then communicated in parts to the corresponding ranks through PETSc's collective \verb|Assembly| routines. The iterative method chosen to solve the non-symmetric pressure system, arising from the flow network, is GMRES together with a left algebraic multi-grid preconditioner supplied via hypre \cite{hypre-web-page}.
\subsection{Limitations} \subsection{Limitations}
\hspace{0.5cm}Since the datastructure used to represent the pores in \emph{netflow} is a Python \verb|set|, the order of the pores is arbitrary. In particular this means each MPI process sees a different ordering from eachother, which necessitates initialization of the full system matrix \& r.h.s. on a given root rank, such that the ordering is consistent for all ranks. This requires additional communication, but prevents duplication of the data associated with the matrix etc. on the remaining processes. \hspace{0.5cm}Since the datastructure used to represent the pores in \emph{netflow} is a Python \verb|set|, the order of the pores is arbitrary. In particular, this means each MPI process sees a different ordering from eachother, which necessitates initialization of the full system matrix \& r.h.s. on a given root rank, such that the ordering is consistent for all ranks. This requires additional communication, but prevents duplication of the data associated with the matrix etc. on the remaining processes.
\subsection{Results} \subsection{Results}
\hspace{0.5cm}In order to assess the quality of the pressure-solution obtained by this solver, we study the fluxes induced by the pore pressures for a given base network comprised of 2636 pores. In particular, we look at all in- and out-going fluxes as well as their sum on a per pore basis (except for source/sink pores), obtained from the function \verb|flux_balance()|. When we complete this analysis for all available solvers and compare the results of the parallel PETSc solver with the existing single-core solvers, we see that the parallel version is in complete agreement with the rest in terms of solution quality, as depicted in Figure ~\ref{fig:balance}. \hspace{0.5cm}In order to assess the quality of the pressure-solution obtained by this solver, we study the fluxes induced by the pore pressures for a given base network comprised of 2636 pores. In particular, we look at all in- and out-going fluxes as well as their sum on a per pore basis (except for source/sink pores), obtained from the function \verb|flux_balance()|. When we complete this analysis for all available solvers and compare the results of the parallel PETSc solver with the existing single-core solvers, we see that the parallel version is in complete agreement with the rest in terms of solution quality, as depicted in Figure ~\ref{fig:balance}.
......
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