I wish to generate a periodic Perlin noise on a regular grid. I need to generate several maps, and the grid are quite large, so I wanted to use multiprocessing, to generate one map per core.
The maps are to be plotted on a figure, and put one after the other on a single binary dat file. The maps would be stored in a single numpy array, of size number of maps* number of nodes, so a slice would be a map, and I could hence access different zones of the array at the same time without worries.
I took as reference this thread, which uses a pool and this one, where I used a queue to do some plots in multiprocessing.
I came up with two codes: the one with the queue works fine on my own computer, but not on the workstations of my lab or on my professional laptop: i have no error messages, it just freezes at some point. The second one works just fine, and I find it simpler than the first example, since I just write directly in the numpy array. (I didn't quite understood the need for all the functions and the init for the async case of the first link.)
My question is: why does my first code have troubles ? I only put below the pieces of code I thought relevant.
Thanks for your help.
First attempt:
def generate_irradiation_maps(rad_v):
while tasks_queue.empty() == False:
print("fetching work ...")
map_index = tasks_queue.get() # get some work to do from the queue
print("----> working on map: %s" % map_index)
perm = range(permsize)
random.shuffle(perm)
perm += perm
for i in range(nb_nodes):
# call the perlin function: fBm
rad_v[map_index, i] = fBm(perm, x[i] * freq, y[i] * freq, int(sizex * freq), int(sizey * freq), octs, persistance)
rad_v[map_index, :] = rad_v[map_index, :] + abs(min(rad_v[map_index, :]))
rad_v[map_index, :] = rad_v[map_index, :] / max(rad_v[map_index, :])
figure = plt.figure(figsize=(20, 7))
plt.tricontourf(x, y, rad_v[map_index, :])
plt.axis('image')
plt.colorbar(shrink=.5)
figure.savefig('diff_gb_and_pf_irrad_c_map_' + str(map_index) + '.png')
plt.clf()
plt.close()
tasks_queue.task_done() # work for this item finished
start_time = time.time()
nb_maps = 10
nb_proc = 1 # number of processes
print("generating %d irradiation maps" % nb_maps)
irrad_c_base_array = mp.Array(ctypes.c_double, nb_maps * nb_nodes)
irrad_c = np.frombuffer(irrad_c_base_array.get_obj())
irrad_c = irrad_c.reshape(nb_maps, nb_nodes)
tasks_queue = mp.JoinableQueue() # a queue to pile up the work to do
jobs = list(range(nb_maps)) # each job is composed of a map
print("inserting jobs in the queue...")
for job in jobs:
tasks_queue.put(job)
print("done")
# launch the processes
for i in range(nb_proc):
current_process = mp.Process(target=generate_irradiation_maps, args=(irrad_c, ))
current_process.start()
# wait for all tasks to be treated
tasks_queue.join()
Second attempt:
def generate_irradiation_maps(arg_list):
map_index = arg_list[0]
print('working on map %i ' % map_index)
perm = range(permsize)
random.shuffle(perm)
perm += perm
for i in range(nb_nodes):
arg_list[1][i] = fBm(perm, x[i] * freq, y[i] * freq, int(sizex * freq), int(sizey * freq), octs, persistance)
arg_list[1][:] = arg_list[1][:] + abs(min(arg_list[1][:]))
arg_list[1][:] = arg_list[1][:] / max(arg_list[1][:])
# plot
figure = plt.figure(figsize=(20, 7))
#plt.tricontourf(x, y, rad_v[map_index, :])
plt.tricontourf(x, y, arg_list[1][:])
plt.axis('image')
plt.colorbar(shrink=.5)
figure.savefig('diff_gb_and_pf_irrad_c_map_' + str(map_index) + '.png')
plt.clf()
plt.close()
start_time = time.time()
nb_maps = 2
nb_proc = 2 # number of processes
print("generating %d irradiation maps" % nb_maps)
irrad_c_base_array = mp.Array(ctypes.c_double, nb_maps * nb_nodes) # we build shared array, accessible from all process. we don't access the same zones.
irrad_c = np.frombuffer(irrad_c_base_array.get_obj())
irrad_c = irrad_c.reshape(nb_maps, nb_nodes)
args = [[i,irrad_c[i,:]] for i in range(nb_maps)]
with closing(mp.Pool(processes=nb_proc)) as jobs_pool:
jobs_pool.map_async(generate_irradiation_maps,args)
jobs_pool.join()