Skip to content

Recursion error pickling step functions #4273

Closed
@rpgoldman

Description

@rpgoldman

Description of your problem

First reported on #3811

When testing on Mac (#3811) or Windows (#4269), RecursionError: maximum recursion depth exceeded in comparison errors in TestDensityDist in parallel_sampling.py when pickling step_method:

pymc3/parallel_sampling.py:421: in __init__
    step_method_pickled = pickle.dumps(step_method, protocol=-1)

Checking with pdb, we try to save the logp of a DensityDist. This leads to needing to pickle Normal.logp which leads to needing to pickle pymc3.distributions.continuous.Normal and I fear to trying to pickle all of pymc3.

It is odd that this shows up on Mac and Windows, but not on our Linux tests.

Please provide the full traceback.

From @MarcoGorelli :

2020-11-29T10:28:07.9704940Z =================================== FAILURES ===================================
2020-11-29T10:28:07.9705530Z _________ TestDensityDist.test_density_dist_with_random_sampleable[()] _________
2020-11-29T10:28:07.9705980Z 
2020-11-29T10:28:07.9706630Z self = <pymc3.tests.test_distributions_random.TestDensityDist object at 0x7fe5ab3d6358>
2020-11-29T10:28:07.9707300Z shape = ()
2020-11-29T10:28:07.9708190Z 
2020-11-29T10:28:07.9708650Z     @pytest.mark.parametrize("shape", [(), (3,), (3, 2)], ids=str)
2020-11-29T10:28:07.9709320Z     def test_density_dist_with_random_sampleable(self, shape):
2020-11-29T10:28:07.9709830Z         with pm.Model() as model:
2020-11-29T10:28:07.9710220Z             mu = pm.Normal("mu", 0, 1)
2020-11-29T10:28:07.9710690Z             normal_dist = pm.Normal.dist(mu, 1, shape=shape)
2020-11-29T10:28:07.9711190Z             obs = pm.DensityDist(
2020-11-29T10:28:07.9711580Z                 "density_dist",
2020-11-29T10:28:07.9711960Z                 normal_dist.logp,
2020-11-29T10:28:07.9712420Z                 observed=np.random.randn(100, *shape),
2020-11-29T10:28:07.9712860Z                 shape=shape,
2020-11-29T10:28:07.9713260Z                 random=normal_dist.random,
2020-11-29T10:28:07.9713610Z             )
2020-11-29T10:28:07.9714330Z >           trace = pm.sample(100)
2020-11-29T10:28:07.9714630Z 
2020-11-29T10:28:07.9722330Z pymc3/tests/test_distributions_random.py:1151: 
2020-11-29T10:28:07.9722810Z _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
2020-11-29T10:28:07.9723220Z pymc3/sampling.py:553: in sample
2020-11-29T10:28:07.9723730Z     trace = _mp_sample(**sample_args, **parallel_args)
2020-11-29T10:28:07.9724240Z pymc3/sampling.py:1469: in _mp_sample
2020-11-29T10:28:07.9724710Z     pickle_backend=pickle_backend,
2020-11-29T10:28:07.9725200Z pymc3/parallel_sampling.py:421: in __init__
2020-11-29T10:28:07.9726340Z     step_method_pickled = pickle.dumps(step_method, protocol=-1)
2020-11-29T10:28:07.9727030Z pymc3/distributions/distribution.py:516: in __getstate__
2020-11-29T10:28:07.9727600Z     logp = dill.dumps(self.logp)
2020-11-29T10:28:07.9728630Z /usr/local/miniconda/envs/testenv/lib/python3.6/site-packages/dill/_dill.py:273: in dumps
2020-11-29T10:28:07.9729410Z     dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
2020-11-29T10:28:07.9730540Z /usr/local/miniconda/envs/testenv/lib/python3.6/site-packages/dill/_dill.py:267: in dump
2020-11-29T10:28:07.9731240Z     Pickler(file, protocol, **_kwds).dump(obj)
2020-11-29T10:28:07.9732280Z /usr/local/miniconda/envs/testenv/lib/python3.6/site-packages/dill/_dill.py:454: in dump
2020-11-29T10:28:07.9732970Z     StockPickler.dump(self, obj)
2020-11-29T10:28:07.9733580Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:409: in dump
2020-11-29T10:28:07.9734090Z     self.save(obj)
2020-11-29T10:28:07.9734610Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:476: in save
2020-11-29T10:28:07.9735240Z     f(self, obj) # Call unbound method with explicit self
2020-11-29T10:28:07.9736430Z /usr/local/miniconda/envs/testenv/lib/python3.6/site-packages/dill/_dill.py:1127: in save_instancemethod0
2020-11-29T10:28:07.9737270Z     pickler.save_reduce(MethodType, (obj.__func__, obj.__self__), obj=obj)
2020-11-29T10:28:07.9738000Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:610: in save_reduce
2020-11-29T10:28:07.9738520Z     save(args)
2020-11-29T10:28:07.9739030Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:476: in save
2020-11-29T10:28:07.9739660Z     f(self, obj) # Call unbound method with explicit self
2020-11-29T10:28:07.9740310Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:736: in save_tuple
2020-11-29T10:28:07.9740850Z     save(element)
2020-11-29T10:28:07.9741370Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:521: in save
2020-11-29T10:28:07.9741930Z     self.save_reduce(obj=obj, *rv)
2020-11-29T10:28:07.9742520Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:634: in save_reduce
2020-11-29T10:28:07.9743050Z     save(state)
2020-11-29T10:28:07.9743550Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:476: in save
2020-11-29T10:28:07.9744170Z     f(self, obj) # Call unbound method with explicit self
2020-11-29T10:28:07.9745320Z /usr/local/miniconda/envs/testenv/lib/python3.6/site-packages/dill/_dill.py:941: in save_module_dict
2020-11-29T10:28:07.9746070Z     StockPickler.save_dict(pickler, obj)
2020-11-29T10:28:07.9747000Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:821: in save_dict
2020-11-29T10:28:07.9747600Z     self._batch_setitems(obj.items())
2020-11-29T10:28:07.9748210Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:847: in _batch_setitems
2020-11-29T10:28:07.9748730Z     save(v)
2020-11-29T10:28:07.9749230Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:521: in save
2020-11-29T10:28:07.9749780Z     self.save_reduce(obj=obj, *rv)
2020-11-29T10:28:07.9750500Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:634: in save_reduce
2020-11-29T10:28:07.9751030Z     save(state)
2020-11-29T10:28:07.9751540Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:476: in save
2020-11-29T10:28:07.9752160Z     f(self, obj) # Call unbound method with explicit self
2020-11-29T10:28:07.9753540Z /usr/local/miniconda/envs/testenv/lib/python3.6/site-packages/dill/_dill.py:941: in save_module_dict
2020-11-29T10:28:07.9754320Z     StockPickler.save_dict(pickler, obj)
2020-11-29T10:28:07.9754980Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:821: in save_dict
2020-11-29T10:28:07.9755560Z     self._batch_setitems(obj.items())
2020-11-29T10:28:07.9756180Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:847: in _batch_setitems
2020-11-29T10:28:07.9756700Z     save(v)
2020-11-29T10:28:07.9757190Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:521: in save
2020-11-29T10:28:07.9757750Z     self.save_reduce(obj=obj, *rv)
2020-11-29T10:28:07.9758340Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:634: in save_reduce
2020-11-29T10:28:07.9758860Z     save(state)
2020-11-29T10:28:07.9759370Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:476: in save
2020-11-29T10:28:07.9759990Z     f(self, obj) # Call unbound method with explicit self
2020-11-29T10:28:07.9761160Z /usr/local/miniconda/envs/testenv/lib/python3.6/site-packages/dill/_dill.py:941: in save_module_dict
2020-11-29T10:28:07.9761910Z     StockPickler.save_dict(pickler, obj)
2020-11-29T10:28:07.9762560Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:821: in save_dict
2020-11-29T10:28:07.9763150Z     self._batch_setitems(obj.items())
2020-11-29T10:28:07.9763760Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:847: in _batch_setitems
2020-11-29T10:28:07.9764290Z     save(v)
2020-11-29T10:28:07.9764770Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:521: in save
2020-11-29T10:28:07.9765340Z     self.save_reduce(obj=obj, *rv)
2020-11-29T10:28:07.9765920Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:631: in save_reduce
2020-11-29T10:28:07.9766520Z     self._batch_setitems(dictitems)
2020-11-29T10:28:07.9767140Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:847: in _batch_setitems
2020-11-29T10:28:07.9767660Z     save(v)
2020-11-29T10:28:07.9768160Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:521: in save
2020-11-29T10:28:07.9768720Z     self.save_reduce(obj=obj, *rv)
2020-11-29T10:28:07.9769310Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:634: in save_reduce
2020-11-29T10:28:07.9769830Z     save(state)
2020-11-29T10:28:07.9770340Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:476: in save
2020-11-29T10:28:07.9771060Z     f(self, obj) # Call unbound method with explicit self
2020-11-29T10:28:07.9772240Z /usr/local/miniconda/envs/testenv/lib/python3.6/site-packages/dill/_dill.py:941: in save_module_dict
2020-11-29T10:28:07.9772980Z     StockPickler.save_dict(pickler, obj)
2020-11-29T10:28:07.9773620Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:821: in save_dict
2020-11-29T10:28:07.9774210Z     self._batch_setitems(obj.items())
2020-11-29T10:28:07.9774830Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:847: in _batch_setitems
2020-11-29T10:28:07.9775350Z     save(v)
2020-11-29T10:28:07.9775850Z /usr/local/miniconda/envs/testenv/lib/python3.6/pickle.py:496: in save
2020-11-29T10:28:07.9776400Z     rv = reduce(self.proto)
2020-11-29T10:28:07.9776930Z pymc3/distributions/distribution.py:516: in __getstate__
2020-11-29T10:28:07.9777740Z     logp = dill.dumps(self.logp)
2020-11-29T10:28:07.9778290Z E   RecursionError: maximum recursion depth exceeded
2020-11-29T10:28:07.9778900Z !!! Recursion detected (same locals & position)
2020-11-29T10:28:07.9779950Z ----------------------------- Captured stderr call -----------------------------
2020-11-29T10:28:07.9780510Z Only 100 samples in chain.
2020-11-29T10:28:07.9781280Z Auto-assigning NUTS sampler...
2020-11-29T10:28:07.9781840Z Initializing NUTS using jitter+adapt_diag...
2020-11-29T10:28:07.9782470Z Multiprocess sampling (2 chains in 2 jobs)
2020-11-29T10:28:07.9782880Z NUTS: [mu]
2020-11-29T10:28:07.9783760Z ------------------------------ Captured log call -------------------------------
2020-11-29T10:28:07.9784430Z WARNING  pymc3:sampling.py:480 Only 100 samples in chain.
2020-11-29T10:28:07.9785800Z INFO     pymc3:sampling.py:490 Auto-assigning NUTS sampler...
2020-11-29T10:28:07.9786590Z INFO     pymc3:sampling.py:2034 Initializing NUTS using jitter+adapt_diag...
2020-11-29T10:28:07.9787330Z INFO     pymc3:sampling.py:550 Multiprocess sampling (2 chains in 2 jobs)
2020-11-29T10:28:07.9787920Z INFO     pymc3:sampling.py:236 NUTS: [mu]

Versions and main components

  • PyMC3 Version: edbafaa
  • Theano Version: theano-pymc==1.0.11
  • Python Version: 3.7.7
  • Operating system: MacOS 10.15.7
  • How did you install PyMC3: pip

/cc @michaelosthege @MarcoGorelli

Metadata

Metadata

Assignees

Labels

bugwinOSwindows OS related

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions