I ran into an odd issue with my model in NEURON+Python that I think I have fixed but would appreciate further clarity to check that I have addressed it correctly.
I am simulating a large network of endocrine cells with lots of variables and need to run long simulations (15-30 minutes) due to slowly changing hormone concentrations that we are interested in studying. For this reason I have followed the advice here on the forum to break the simulations into chunks and have the following workflow:
Code: Select all
# Create a dictionary with recorded variable names as keys and values as h.Vectors
rec_dict = create_rec_dict(section_list)
# Chunk end times is a list of end times for each chunk
# For example if I was running a 5000 ms simulation in chunks of 1000 ms
# it would be the list [1000, 2000, 3000, 4000, 5000]
for chunk_end_time in chunk_end_times:
# Run simulation until the end of the next time chunk
h.continuerun(chunk_end_time)
# Save chunk data... Omitting code for brevity
# Resize recording vectors so that max amount of memory consumed is close to
# the amount required to store one time chunks worth of data
h.frecord_init()
Code: Select all
import multiprocessing as mp
# Create a dictionary with recorded variable names as keys and values as h.Vectors
rec_dict = create_rec_dict(section_list)
# Create multiprocessing manager to manage data queue
with mp.Manager() as manager:
# Create data queue
data_queue = manager.Queue()
# Create writer process that will get processed data arrays from the data queue and write them to disk
data_writer = mp.Process(target=data_writer_func, args=(data_writer_args))
# Create multiprocessing pool to handle data_processor worker processes
with mp.Pool() as pool:
# Chunk end times is a list of end times for each chunk
# For example if I was running a 5000 ms simulation in chunks of 1000 ms
# it would be the list [1000, 2000, 3000, 4000, 5000]
for chunk_end_time in chunk_end_times:
# Run simulation until the end of the next time chunk
h.continuerun(chunk_end_time)
# Convert time vector to numpy array
time_array = rec_dict["Time"].as_numpy()
# Save chunk data
for var, vec in rec_dict.items():
if var == "Time":
continue
# Convert vector to numpy array
var_array = vec.as_numpy()
# Create worker process to process this data before passing it the data writer
pool.apply_async(target=data_processor, args=(var, var_array, time_array))
# Resize recording vectors so that max amount of memory consumed is close to
# the amount required to store one time chunks worth of data
h.frecord_init()
I tested this by running a very small simulation (takes around 1 second to complete) with 2 time chunks and added the statement
Code: Select all
import time
# Sleep for 10 seconds
time.sleep(10)
Does all this make sense? And if so, does anyone have any recommendations for best practices on how to have multiple processes handle running simulations, processing, and writing data?
Any advice or thoughts are appreciated!