nest-simulator icon indicating copy to clipboard operation
nest-simulator copied to clipboard

Nest simulations cannot be pickled

Open morales-gregorio opened this issue 2 years ago • 4 comments

Hi,

I am using NEST to run many medium size simulations to perform a parameter scan. As part of my workflow the nest simulation gets packaged into a class and at some point pickled for future use.

The problem is that some of the newer objects in nest 3 cannot be pickled at all. In particular the nest.NodeCollection as well as the new devices cause this problem. Not being able to pickle severely limits workflows where many smaller models are used.

Small sample to show the problem:

import nest
import jsonpickle

neuron_params = {'C_m': 250.0, 't_ref': 2.0, 'E_L': 0.0, 'V_reset': 0.0,
                'V_m': 0.0, 'tau_syn_ex': 0.5, 'tau_syn_in': 0.5,
                'tau_m': 20.0, 'V_th': 20.0}

pop = nest.Create('iaf_psc_alpha', n=10, params=neuron_params)
jsonpickle.encode(pop)

which generates this output:

Traceback (most recent call last):
 File "/p/home/jusers/morales-gregorio1/jureca/install/nest-simulator/3.2/default/lib64/python3.9/site-packages/nest/lib/hl_api_helper.py", line 542, in get_parameters
   sr(cmd)
 File "/p/home/jusers/morales-gregorio1/jureca/install/nest-simulator/3.2/default/lib64/python3.9/site-packages/nest/ll_api.py", line 113, in catching_sli_run
   raise exceptionCls(commandname, message)
nest.lib.hl_api_exceptions.DictError: DictError in SLI function get_d: Key '/__getnewargs__' does not exist in dictionary.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
 File "/p/project/cjinb33/comet2ltl/cometrepo/tests/test_nest_nodecollection.py", line 10, in <module>
   jsonpickle.encode(pop)
 File "/p/home/jusers/morales-gregorio1/jureca/.local/lib/python3.9/site-packages/jsonpickle/pickler.py", line 134, in encode
   context.flatten(value, reset=reset), indent=indent, separators=separators
 File "/p/home/jusers/morales-gregorio1/jureca/.local/lib/python3.9/site-packages/jsonpickle/pickler.py", line 260, in flatten
   return self._flatten(obj)
 File "/p/home/jusers/morales-gregorio1/jureca/.local/lib/python3.9/site-packages/jsonpickle/pickler.py", line 264, in _flatten
   result = self._flatten_impl(obj)
 File "/p/home/jusers/morales-gregorio1/jureca/.local/lib/python3.9/site-packages/jsonpickle/pickler.py", line 290, in _flatten_impl
   return self._pop(self._flatten_obj(obj))
 File "/p/home/jusers/morales-gregorio1/jureca/.local/lib/python3.9/site-packages/jsonpickle/pickler.py", line 319, in _flatten_obj
   raise e
 File "/p/home/jusers/morales-gregorio1/jureca/.local/lib/python3.9/site-packages/jsonpickle/pickler.py", line 313, in _flatten_obj
   return flatten_func(obj)
 File "/p/home/jusers/morales-gregorio1/jureca/.local/lib/python3.9/site-packages/jsonpickle/pickler.py", line 365, in _ref_obj_instance
   return self._flatten_obj_instance(obj)
 File "/p/home/jusers/morales-gregorio1/jureca/.local/lib/python3.9/site-packages/jsonpickle/pickler.py", line 401, in _flatten_obj_instance
   has_getnewargs = util.has_method(obj, '__getnewargs__')
 File "/p/home/jusers/morales-gregorio1/jureca/.local/lib/python3.9/site-packages/jsonpickle/util.py", line 81, in has_method
   if not hasattr(obj, name):
 File "/p/home/jusers/morales-gregorio1/jureca/install/nest-simulator/3.2/default/lib64/python3.9/site-packages/nest/lib/hl_api_types.py", line 535, in __getattr__
   return self.get(attr)
 File "/p/home/jusers/morales-gregorio1/jureca/install/nest-simulator/3.2/default/lib64/python3.9/site-packages/nest/lib/hl_api_types.py", line 394, in get
   result = get_parameters(self, params[0])
 File "/p/home/jusers/morales-gregorio1/jureca/install/nest-simulator/3.2/default/lib64/python3.9/site-packages/nest/lib/hl_api_helper.py", line 545, in get_parameters
   result = nc.get()[param]  # If the NodeCollection is a composite.
KeyError: '__getnewargs__'

Can this be solved in a simple way?

I can on my side store the object id and reconstruct them manually when needed, although this defeats the purpose of having nice NodeCollection and Device objects.

Thanks, Aitor

morales-gregorio avatar Mar 22 '22 10:03 morales-gregorio

Have you tried with plain pickle? See an example here.

stinebuu avatar Mar 22 '22 14:03 stinebuu

Similar error:

import nest
import pickle

neuron_params = {'C_m': 250.0, 't_ref': 2.0, 'E_L': 0.0, 'V_reset': 0.0,
                'V_m': 0.0, 'tau_syn_ex': 0.5, 'tau_syn_in': 0.5,
                'tau_m': 20.0, 'V_th': 20.0}

pop = nest.Create('iaf_psc_alpha', n=10, params=neuron_params)
with open('foo.pkl', 'wb') as f:
    pickle.dump(pop, f, pickle.HIGHEST_PROTOCOL)

Output:

Traceback (most recent call last):
  File "/p/home/jusers/morales-gregorio1/jureca/install/nest-simulator/3.2/default/lib64/python3.9/site-packages/nest/lib/hl_api_helper.py", line 542, in get_parameters
    sr(cmd)
  File "/p/home/jusers/morales-gregorio1/jureca/install/nest-simulator/3.2/default/lib64/python3.9/site-packages/nest/ll_api.py", line 113, in catching_sli_run
    raise exceptionCls(commandname, message)
nest.lib.hl_api_exceptions.DictError: DictError in SLI function get_d: Key '/__getstate__' does not exist in dictionary.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/p/project/cjinb33/comet2ltl/cometrepo/tests/test_nest_pickle_nodecollection.py", line 10, in <module>
    pickle.dump(pop, f, pickle.HIGHEST_PROTOCOL)
  File "/p/home/jusers/morales-gregorio1/jureca/install/nest-simulator/3.2/default/lib64/python3.9/site-packages/nest/lib/hl_api_types.py", line 535, in __getattr__
    return self.get(attr)
  File "/p/home/jusers/morales-gregorio1/jureca/install/nest-simulator/3.2/default/lib64/python3.9/site-packages/nest/lib/hl_api_types.py", line 394, in get
    result = get_parameters(self, params[0])
  File "/p/home/jusers/morales-gregorio1/jureca/install/nest-simulator/3.2/default/lib64/python3.9/site-packages/nest/lib/hl_api_helper.py", line 545, in get_parameters
    result = nc.get()[param]  # If the NodeCollection is a composite.
KeyError: '__getstate__'

morales-gregorio avatar Mar 22 '22 15:03 morales-gregorio

I could circumvent this problem by doing the following:

self.population = pop.tolist()

(...)

# Elsewhere in the code
pop = nest.NodeCollection(self.population)

So that when self is pickled there is only a list in there, luckily I also have the nest module pickled thus this solution works. Still a bit annoying that the NodeCollection cannot be pickled, since that would be ideal for cases with many smaller simulations

morales-gregorio avatar Mar 22 '22 15:03 morales-gregorio

Issue automatically marked stale!

github-actions[bot] avatar May 22 '22 08:05 github-actions[bot]

@morales-gregorio Pickling NEST simulations is not possible. Any pickling from the Python level would not store the internal state of the network, and implementing complete pickling of the kernel in a robust way would be an extremely complex task.

But please see this example for storing and restoring networks, which hopefully will provide much of the functionality you need.

I am closing this issue since a general solution is not feasible.

heplesser avatar Nov 28 '22 22:11 heplesser