2

I am trying to parallelize the python function below, which is involved in finite element analysis. In particular, I am trying to make the for loop in the function runs in parallel. I have done it in Matlab using parfor, and I am trying to do the same in python.

def assemble(u):
K=np.zeros((ndof,ndof)) # initializing global stiffness matrix
Fint=np.zeros(ndof)
Fext=np.zeros(ndof)
for iel in range(tne):
    elnodes=elems[iel,:] # nodes of the local elements
    xcel=nodes[elnodes,0] # x-coordinates for the local elements
    ycel=nodes[elnodes,1] # y-coordinates for the local elements
    zcel=nodes[elnodes,2] # z-coordinates for the local elements
    dof=np.array([3*elnodes[0],3*elnodes[0]+1,3*elnodes[0]+2,3*elnodes[1],\
                  3*elnodes[1]+1,3*elnodes[1]+2,3*elnodes[2],3*elnodes[2]+1,\
                  3*elnodes[2]+2,3*elnodes[3],3*elnodes[3]+1,3*elnodes[3]+2,\
                  3*elnodes[4],3*elnodes[4]+1,3*elnodes[4]+2,3*elnodes[5],\
                  3*elnodes[5]+1,3*elnodes[5]+2,3*elnodes[6],3*elnodes[6]+1,\
                  3*elnodes[6]+2,3*elnodes[7],3*elnodes[7]+1,3*elnodes[7]+2]).flatten()
    u_el=u[dof]
    strain,stress=SS(xcel,ycel,zcel,u_el)
    ESM,Fint_e,Fext_e=Elem_KF(xcel,ycel,zcel,strain,stress)
    K[np.ix_(dof,dof)]+=ESM
    Fint[dof]+=Fint_e
    Fext[dof]+=Fext_e
R=Fext-Fint
return K,Fint,Fext,R

I have tried this, but it did not work for me:

def assemble(u):
dof2    = np.zeros((tne,24))
Fint_e2 = np.zeros((tne,24))
Fext_e2 = np.zeros((tne,24))
ppp = Pool(2)
for iel in range(tne):
    Fint_e2[iel,:], Fext_e2[iel,:], dof2[iel,:] = ppp.apply(workers,args=(iel,u,))
ppp.close()
ppp.join()
return Fint_e2, Fext_e2, dof2

def workers(iel, u):
print(iel)
elnodes=elems[iel,:].long() # nodes of the local elements
xcel=nodes[elnodes,0] # x-coordinates for the local elements
ycel=nodes[elnodes,1] # y-coordinates for the local elements
zcel=nodes[elnodes,2] # z-coordinates for the local elements
dof=np.array([3*elnodes[0],3*elnodes[0]+1,3*elnodes[0]+2,\
                  3*elnodes[1],3*elnodes[1]+1,3*elnodes[1]+2,\
                  3*elnodes[2],3*elnodes[2]+1,3*elnodes[2]+2,\
                  3*elnodes[3],3*elnodes[3]+1,3*elnodes[3]+2,\
                  3*elnodes[4],3*elnodes[4]+1,3*elnodes[4]+2,\
                  3*elnodes[5],3*elnodes[5]+1,3*elnodes[5]+2,\
                  3*elnodes[6],3*elnodes[6]+1,3*elnodes[6]+2,\
                  3*elnodes[7],3*elnodes[7]+1,3*elnodes[7]+2]).flatten()
u_el=u[dof]
strain,stress = Stress_Strain(xcel,ycel,zcel,u_el)
Fint_e,Fext_e = KEL(xcel,ycel,zcel,strain,stress)
return Fint_e, Fext_e, dof

Any help would be highly appreciated. Thanks!

2
  • 2
    Does this answer your question? stackoverflow.com/questions/4682429/parfor-for-python There are some nice answers there. Commented May 6, 2020 at 0:38
  • 1
    loops in python are not as fast as in matlab - much slower actually. You will have a better time trying to vectorize your code (if at all possible) instead of trying to get it to run fast with multiprocessing or concurrent.futures - because you will pay for the performance hit of pickling across processes and get no CPU-bound speed improvements with threads because of the GIL Commented May 6, 2020 at 1:42

1 Answer 1

1

You can use Pools, to use multiple processes at the same time.

from multiprocessing import Pool

p = Pool(n_threads)

for iel in range(tne):
   #function will calculate all the parameters you have inside the loop
   results = p.apply(function,args=(x,y,z,etc,))  

#wait for all threads to return their value
p.close()
p.join()
Sign up to request clarification or add additional context in comments.

1 Comment

Hi Ramiro, Thanks for the reply. I tried something along the lines you suggested, but it did not work for me. Please see my answer below.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.