EDIT: My goal with this post is to understand the source of the time-drain. I welcome other recommendations as well, but my main concern, and I want to learn about is why my code is not speeding up with parallelization? What is it that's causing the parallelization to slow down?
I previously asked a question about this, and I now realize that it wasn't a good one. I apologize for the poor post. So I'm re-asking having put more effort into solving it.
I have managed to implement a parallelized solution. However, the parallelized code is much much much slower than the serialized version.
EDIT: The foo()
function below is rather simple, and can be put more concisely, but the real version of the function is a bit more complicated. The main problem is still the fact that at thousands of arrays, each of length ~70,000, the sheer number of comparisons is what's causing the slowness. So parallelization seems to be the best solution here. Of course, recommendations for making the steps more efficient are welcome, and I appreciate any such suggestions.
Problem
Consider a list of numpy arrays. I need to do pairwise comparisons on these arrays in the list. My real problem has thousands of arrays of length ~70,000, but the toy example below has much smaller numbers (can be adjusted with the listLen
and arrayLen
variables though)
Attempt
Here foo()
is the comparison function that will be used. If you try playing around with arrayLen
and listLen
, you'll see that no matter what values you choose, the parallelized function do_calculations_mp
is always slower than the non-parallelized version do_calculations_no_mp
. From what I've read, multiprocesing.Process
has less overhead than multiprocess.Pool
, so it shouldn't be taking this long, right?
I'd really appreciate any help on this.
import numpy as np
from multiprocessing import Process
import itertools
import random
import sys
from datetime import datetime
def foo(arr1, arr2):
matches = 0
for i in range(len(arr1)):
if arr1[i] == arr2[i]:
matches += 1
return(matches)
def do_calculations_mp(aList):
flag_indices = []
processes = []
index_combns = list(itertools.combinations(range(len(aList)),2))
for i,j in index_combns:
p = Process(target = foo, args = (aList[i], aList[j]))
processes.append(p)
p.start()
for procs in processes:
procs.join()
return(flag_indices)
def do_calculations_no_mp(aList):
flag_indices = []
index_combns = list(itertools.combinations(range(len(aList)),2))
for i,j in index_combns:
numMatches = foo(aList[i], aList[j])
return(flag_indices)
if __name__ == '__main__':
listLen = 50
arrayLen = 300
# Creates a list of listLen arrays, where each array has length arrayLen
myList = [np.array([random.choice([0,1,2,5]) for i in range(arrayLen)]) for x in range(listLen)]
print("Processing No MP: " + str(datetime.now()))
flagged = do_calculations_no_mp(myList)
print("Done processing No MP: " + str(datetime.now()))
print("Processing MP: " + str(datetime.now()))
flagged_mp = do_calculations_mp(myList)
print("Done processing MP: " + str(datetime.now()))