'How to properly parallelizing a for-loop in python with shared variables?
This is my first attempt for multiprocessing in python and I am having hard time finding a fast solution for parallelizing my code. I do my best to explain my situation.
This is the code I am trying to parallelizing (the main problem is the for-loop):
Original code:
if __name__ == "__main__":
n = 10
filling_array = np.ones((n, n))*-1
reading_array = np.ones((n, n))*10
for i in range(n):
for j in range(int(i/2)):
filling_array[i, j] = 10*i + reading_array[i, j]
print(filling_array.sum(axis=1), 'end')
And this is my solution:
def child_p(i,
filling_array,
reading_array):
for j in range(int(i/2)):
filling_array[i, j] = 10*i + reading_array[i, j]
return filling_array
if __name__ == "__main__":
n = 10
filling_array = np.ones((n, n))*-1
reading_array = np.ones((n, n))*10
final_array = np.zeros((n, n))
with Pool(cpu_count()) as pool:
result = pool.starmap(child_p,
zip(
range(n),
repeat(filling_array, n),
repeat(reading_array, n)
)
)
for iter in range(n):
final_array[iter, :] = result[iter][iter, :]
print(final_array.sum(axis=1), 'end')
Literally, the child function act like the for-loop to fill the filling_array, using the reading array. I have separated the "for-loop" as a child function.
My solution is faster than the original for-loop but it is very slow and memory-heavy!
I think the main problem is where the pool.starmap() tries to copying/mapping the two arrays into the function (the arrays are very large).
Would you please guide me? Is there a way that I share these large arrays (in my original code, there are 5 reading_array and 1 filling_array and they are large)?
How can I do that?
Solution 1:[1]
This is what I did after, in order to solve my problem, it somehow works, but Im not sure how good it is:
Edited
I have tried the method in this website, but for two arrays, like this:
def child_p(i,
filling_array_specs,
reading_array_specs,):
fa_name, fa_shape, fa_dtype = filling_array_specs
fa_shm = SharedMemory(fa_name)
filling_array = np.ndarray(shape=fa_shape, dtype=fa_dtype, buffer=fa_shm.buf)
ra_name, ra_shape, ra_dtype = reading_array_specs
ra_shm = SharedMemory(ra_name)
reading_array = np.ndarray(shape=ra_shape, dtype=ra_dtype, buffer=ra_shm.buf)
for j in range(int(i/2)):
filling_array[i, j] = 10*i + reading_array[i, j]
if __name__ == "__main__":
n = 10
filling_array = np.ones((n, n))*-1
reading_array = np.ones((n, n))*10
fa_shape, fa_dtype = filling_array.shape, filling_array.dtype
ra_shape, ra_dtype = reading_array.shape, reading_array.dtype
with SharedMemoryManager() as smm:
fa_shm = smm.SharedMemory(filling_array.nbytes)
shm_filling_array = np.ndarray(shape=fa_shape, dtype=fa_dtype, buffer=fa_shm.buf)
np.copyto(shm_filling_array, filling_array)
filling_array_specs = [fa_shm.name, fa_shape, fa_dtype]
ra_shm = smm.SharedMemory(reading_array.nbytes)
shm_reading_array = np.ndarray(shape=ra_shape, dtype=ra_dtype, buffer=ra_shm.buf)
np.copyto(shm_reading_array, reading_array)
reading_array_specs = [ra_shm.name, ra_shape, ra_dtype]
with Pool(cpu_count()) as pool:
pool.starmap(child_p,
zip(
range(n),
repeat(filling_array_specs, n),
repeat(reading_array_specs, n)
)
)
print(shm_filling_array.sum(axis=1), 'end')
Please note that I passed each array's specs [sh_name, shape, dtype] to the child_p.
So far it seems working, but I am not sure how fast it is with my large arrays, will update this post regarding the time.
Edit 2:
# for n = 2000
# The original for-loop took 82.13 sec
# The shared memory method took 17.39 sec
Is this the fastest method I can achive? Or there are other methods that you think would works better?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
