-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix pickling of states and distributions #305
Conversation
…ckling of states.
return dct | ||
|
||
def __setstate__(self, state): | ||
self.__init__(state['_gen'], state['rng']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand that it's not great form to call __init__
from __setstate__
, in case init changes in some unexpected way. Better practice could be to copy the relevant guts out of init to a separate function that's call both by __init__
and __setstate__
, but meh?
starsim/states.py
Outdated
|
||
def __getstate__(self): | ||
slots_dict = {s: getattr(self, s) for s in self.__slots__ if hasattr(self, s) and getattr(self, s) is not None} | ||
return (self.__dict__, slots_dict) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is basically reimplementing __getstate__
... because I don't know how to call the default state getter. Ideas?
starsim/states.py
Outdated
for st in state: | ||
for k, v in st.items(): | ||
setattr(self, k, v) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, basically just the default state setter because I'm not sure what else to do.
sims = ss.MultiSim([ss.Sim(pars, label='Sim1'), ss.Sim(pars, label='Sim2')]) | ||
sims.run() | ||
s1, s2 = sims.sims | ||
assert np.allclose(s1.summary[:], s2.summary[:], rtol=0, atol=0, equal_nan=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switched from parallel to MultiSim, now that we have that functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was a bit unsure what the
then states like |
@RomeshA - these changes are intended to enable parallel processing, e.g. |
@RomeshA To fix that particular issue, we could change it to def __getattr__(self, attr):
""" Make it behave like a regular array mostly -- enables things like sum(), mean(), etc. """
if attr in ['__deepcopy__', '__setstate__']:
return self.__getattribute__(attr)
else:
return getattr(self.values, attr) Buuuuut ... this is definitely ugly and probably not super performant, though not sure if this path is encountered enough for it to matter. |
NB: on import starsim as ss
import sciris as sc
s = ss.Sim(pars=dict(diseases='sir', networks='random'))
s.initialize()
s2 = sc.dcp(s)
s.run()
s2.run()
s.plot()
s2.plot() |
@daniel-klein I pushed this change to |
Those changes above should fix @cliffckerr's example - the issue was that we were inadvertently deep-copying arrays that were supposed to be references to other existing arrays, so the discrepancy would occur because the first 10 time steps would update the inadvertently copied arrays, and then when dead agents are removed at t=10, the views were re-connected but because the proper arrays hadn't been used up to that point, they would still contain the original values (e.g., everyone susceptible). So the fix is to make sure that the arrays are re-linked when copied/unpickled |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to all work now with the latest set of changes!
Not pretty, but seems to work. Would appreciate a review. Should close #257 and now we can run MultiSim!