-
Notifications
You must be signed in to change notification settings - Fork 371
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
Can we replace nest.Prepare/nest.Run/nest.Simulate/nest.Cleanup by a single or two wrapper command(s)? #1773
Comments
I think |
Oh, my proposal would check whether So as I understand, the only overhead would be that if check. |
I realized overnight that the way I described this issue, describing every change to the python functions I propose, may obscure the rather straightforward basic idea. I prepended the message with a comment accordingly. |
@Silmathoron @jd41 There is a bool that checks for nest-simulator/nestkernel/simulation_manager.h Lines 214 to 217 in aa894c1
This check should also be added to I don't really agree about having a wrapper around |
@stinebuu The difference between the current In the proposed solution, |
Thanks for the answer, by the way! Then whatever is changed seems to be
easier to change in C++ indeed.
|
Given @stinebuu 's answer, the proposed changes seem pretty straightforward. Regarding the removal of |
As I understand currently, I didn't get anything wrong with my original proposal, and it would work out that way. It would also be in the same order of straightforwardness-to-implement as @Silmathoron's proposal. I also still believe that it would be an improvement. In short, while emitting the errors proposed by @Silmathoron would clearly improve the situation, hitting upon, understanding and fixing the source of an error message (running the script on a cluster, which we can assume is clogged until tomorrow, with the error occurring after 3 hours of runtime...) and noticing/reading/understanding/judging the relevance of/acting upon some documentation (the appropriate part of the Running Simulations guide) always has costs as well, and interface complexity has an expectation value of costs in general. In contrast, if the stuff is done correctly automatically, the cost to the user is 0 (except when they spend time reading about how not using GetStatus between Runs improves performance), and the benefit may still accrue (either if they just don't use SetStatus, or rewrite their code to use it less often). Having the complexity of people managing The two people I talked with about using In my case, it turned out not to have had a benefit (because I need
You can multiply the third cost by everyone ever learning about NEST and hitting upon My experience with NEST documentation and error messages is that they typically don't immediately make clear what the problem is and how to fix it. So if an error message is tailor-made for my issue #1772, I think it's at least possible that it won't be as helpful to the next person as we may at first believe. Again, not thinking of the possible trouble may just mean something about our imaginations... And this cost accounting just concerns the concrete problem described in #1772. Is there some other pitfall that could occur? A bug in PyNEST? Someone triggering a hard-to-catch error that doesn't occur every time by using SetStatus, or mixing up the words ^1 I do realize that a more experienced person will have a more efficient workflow, that there are some other optimization potentials for me to reduce that timesink etc, that learning something has benefits beyond one-shot... but right now, I was only talking about the concrete consequences of that doc+code to me as of two weeks ago. |
I reformatted my comment and would also like to suggest another solution, a combination of the two previous proposals in a way. We implement the original proposal in the issue, and in addition, whenever SetStatus is called in a prepared state, we emit a warning ("Cleaning up NEST kernel before using SetStatus. A performance penalty will be incurred in the next Run. See https://nest-simulator.readthedocs.org/guide-xyz" for details" or similar)... This would seem to me to have all the advantages of making the user understand what happens as in @Silmathoron's variant, and little of the complexity disadvantages, except for someone who knows what they are doing and is annoyed by such a warning. |
I asked around in the last group meeting. Of ~5 NEST users present (not counting me), one person had read the "Running Simulations" guide at some point, and if I understood correctly, this person said that they don't really remember what was written in there either. I also searched on GitHub for how often "nest.Prepare()" is currently used in Python code. I am not sure how exactly they are counted, and I get a few false positives - but I find 4400 code results for Python code that uses "nest.Create" (a proxy for code using NEST in general) and ~20 results for Python code that uses "nest.Prepare()" (a proxy for code using the current Prepare-Run-Cleanup mechanism). |
@jd41 sorry for the delay in responding, things suddenly got in the way. When we benchmark NEST, we are (often) interested in the individual I am also a bit skeptical about removing I am also skeptical because as I said previously, Don't get me wrong, though, it is definitely a problem that users have problems understanding the documentation, and/or that they are calling functions they shouldn't in between the scope and an error does not occur. This should definitively be fixed!! I think we should update both the documentation, and throw exceptions when things are wrong. |
Maybe we should write this to be discussed at the next VC? (@terhorstd) |
@jd41 @Silmathoron We will discuss this issue during the open NEST Developer VC today, and it would be great if you join so we get your inputs.:) |
@stinebuu Thanks for putting it on the agenda, I'll be there :) |
Since I was thinking about this during the VC, I came up with an additional possible implementation, so here is a post to summarize what might be possible:
To me:
|
The original reason for splitting I would be cautious to automatically call In summary, I completely agree with @stinebuu's proposal to fix the documentation and throw errors when dangerous operations are summoned by users. The real work here is to identify, which operations are OK and which are not. |
Hey @Silmathoron actually the initial message in this thread did include a change to SetStatus (in the bullet points), but I forgot to mention it explicitly in the Update: part.^1 I think the option of manual cleanup is needed even in your variant 3, people must be able to sync/close files manually in the middle of the simulation if they want to access recordings on file before a script ends. A part of the issue @stinebuu's raises "A lot of the time it might be very important for them to call Cleanup and then they will not, because they do not know that they have to." is that with just a Run, they may not even know there is a problem (do you have another example of when people may need to call Cleanup manually @stinebuu?). I'd also like to add variant 4, which means variant 3 (+manual cleanup)+adding warnings/information messages as here.^2 To my mind, this would mostly solve @stinebuu and @jougs worry that users would not be aware of what is happening. A concrete scenario I see how something can go wrong if the Prepare/Cleanup is not done automatically (besides the added time of understanding, adding these functions and getting them to run at all, and general inherent risk of complexity) is if people have included control logic in their scripts where they use SetStatus in the middle with some, but not all, parameter settings, and something goes wrong with that. Without automatically doing the right thing, this might then cause errors and add to the misery of whatever poor soul tries to rerun the code from a paper... There have been several misunderstandings and apparently lots of typing time in this thread so far, if you are interested in furthering this discussion, I think it should be finalized by voice, ideally among less than 5 people. I'll also ask my "NEST user focus group" (i.e. the group meeting) tomorrow to understand better how often these potential problems actually arise. ^1 As this was unclear, I should have taken my own advice to be concise, bullet-pointed, and non-redundant in that message... |
Brief recap from the "focus group" (9 NEST users including me):
|
It might be that syncing and closing mid-flight is not needed often, but everyone who wants to analyze their data while the simulation is still running needs to be able to do this. Especially in long-running experiments involving plasticity this is crucial to not waste allocated compute time (and thus energy) on a possibly dead network. And my other point still stands: If If anything, I'd be for removing |
I'm not so enthusiastic about that right now tbh but may have a different opinion on Monday, what do you think @stinebuu @Silmathoron? |
Sorry, had to correct some formatting in my last comment |
There still seems to be a formatting issue (or I don't get what the "Sphinx .. warning .. :: role" part is meant to mean). I also changed your numbering above, so it is easier to quote.
Yes, but I'd rather have the user always do this explicitly, as this might require moving files away or setting new names to prevent errors or overridden files
Most likely, some destructor will write the data when the process ends.
Not sure at the moment.
This is exactly my point. I want users to be aware that I think what my scepticism against changing the current functions boils down to, is the following: |
I think you and I are saying similar things here =) |
This whole thing was built for the small minority of users who would need to poke around with internals -- specifically, collect data during a simulation phase, as per NestIO. I'd avoid doing any complicated work here -- it would defeat the purpose -- beyond simply throwing an exception on empirically defined "bad behavior", since everything is undefined in terms of these calls. Or rewrite NEST from scratch? As I recall, the original issues discussed this already, and decided already that without a significant cleanup of the NEST internals, the only choices left are: a) There Be Dragons Here; or b) don't expose these calls at all. |
I would like to take up the discussion here again, because we still do not raise exceptions when any network-modifying commands ( Following Python's explicit is better than implicit maxime, I would suggest the following approach:
|
would I rather like your proposal about limiting available functions to |
@heplesser If |
@stinebuu but are there cases where you could not replace these calls to |
@stinebuu They should be private on the PyNEST level, so you could still use them if you wanted ;). With the built-in timers provided by #1778, timing from the Python level becomes maybe also less important. And finally, I guess you could measure prepare/cleanup times even with a context by smart placement of timers: prepare_start = time.time()
with nest.RunManager():
sim_start = time.time()
nest.Run(1000)
sim_stop = time.time()
cleanup_stop = time.time()
t_prep = sim_start - prepare_start
t_sim = sim_stop - sim_start
t_cleanup = cleanup_stop - sim_stop |
Yes, this would work for me :) |
We looked at this again during the NEST 3.0 Finalton (08/06/2020). The issue with calling I am thus closing this issue, as it will be fixed with #2060. |
See also #1772.
Update: The basic idea of this change is to keep track of whether the simulation is currently in a prepared state (e.g.
nest.Prepare()
has been called, butnest.Cleanup()
hasn't), and putnest.Prepare
andnest.Cleanup
into wrappers which only invoke the expensive kernel functions if they are necessary/appropriate according to that status. The current motivation for exposingPrepare
/Run
/Cleanup
rather than just one simulation command to the PyNEST user is that the user can save time by not cleaning up between runs (see the Running simulations guide). With the wrappers, the overhead of callingnest.Prepare
twice becomes negligible, and we can remove much of that complexity from the API and documentation (see below for details and precisifications).Is your feature request related to a problem? Please describe.
It is related to the problem I described in #1772, which is related to the fact that the user has to learn about 4 commands (Update: actually 5, if you include the RunManager)+at least 1 pitfall (see #1772 for the pitfall) for running simulations once vs. in stages. It seems to me that, by introducing some wrappers on the PyNEST level, the pitfall would vanish, only 2 functions would be necessary to document/understand (and the others could be deprecated/removed), and almost all users would only need to learn about 1 of them. I write here to understand whether I am missing something and it's more complicated in reality.
Describe the solution you'd like
False
.nest.Prepare()
is replaced by a wrapper that only calls the originalnest.Prepare()
ifprepared == False
, and setsprepared = True
afterwards.nest.Run()
is replaced by a wrapper that checks ifprepared == True
, and callsnest.Prepare()
before the originalnest.Run()
if it was false. UPDATE/Clarification: If it finds thatprepared == True
already, it skips thePrepare()
call. Another UPDATE: Actually, because the new Prepare() checks whetherprepared == True
already and doesn't invoke the NEST kernel if it is, it wouldn't hurt performance too much to skip the check in the new Run() function.nest.Simulate()
is replaced by a wrapper that calls the newnest.Run()
(which in turn will callnest.Prepare()
if the simulation wasn't prepared), followed bynest.Cleanup()
.nest.SetStatus()
is replaced by a wrapper that checks ifprepared == False
, and callsnest.Cleanup()
before the originalnest.SetStatus()
otherwise. UPDATE: We also could skip the if check without much performance cost, as the newnest.Cleanup()
will also check whetherprepared == True
and not do anything expensive if it is already/stillFalse
.model.set()
changed in the same way asnest.SetStatus()
.nest.Cleanup()
is replaced by a wrapper that only calls the originalnest.Cleanup()
ifprepared == True
, and setsprepared = False
afterwards.atexit.register(Cleanup)
from theatexit
module in the PyNEST initialisation code so thatnest.Cleanup()
is called on program exit automatically (would this work in the way I understand it works?).nest.RunManager()
deprecated/removed.Alternatively, one could implement these wrapper functions in the NEST kernel.
If I understand correctly, these changes by themselves would be completely backwards-compatible and not change the behaviour of currently correct PyNEST simulation code (as well as introducing minimal overhead). However, they would make life easier for the user, who now can usually call
nest.Run()
instead of understanding and distinguishing Prepare/Cleanup/Simulate/Run. Only in the presumably rare case where they want to close/sync files in the middle of the simulation script, they would also need to know about and callnest.Cleanup()
. The other functions (nest.Simulate()
andnest.Prepare()
) could be deprecated/removed from the documentation and user-visible API in the next step. The SetStatus-after-Prepare pitfall (#1772) would vanish.Describe alternatives you've considered
I'm somewhat on the fence on whether to call the new
nest.Run()
function "nest.Run()
" or "nest.Simulate()
", because:In the variant described above, the remaining difference between the new
nest.Run()
and the newnest.Simulate()
would be that, as is the case currently,nest.Simulate()
will be guaranteed to exit with the kernel in a cleaned-up state/files closed/whatever.If we instead call the function that becomes the new
nest.Run()
above "nest.Simulate()
", I see two advantages and a disadvantage:Advantages: I guess that most simulation code out there is fine with an unclean kernel after Simulate, and the cleanup being done automatically once on script termination (with the
atexit
handler). So just calling the newnest.Run()
nest.Simulate()
will be fine, and scripts will continue to work without users having to learn about a new command/changing their scripts/understanding one more entry in the NEST-X-to-X+1 porting guide. Scripts that didn't care about using Prepare/Run/Simulate before will can become faster.Disadvantage: However, if a script depends on the kernel being cleaned up after a
Simulate()
call in the middle of the python code, and theSimulate
suddenly stops doing that, it may cause a lot of grief to whatever student tries to port that script to the next NEST version and doesn't understand why it doesn't work anymore.Am I missing something here, and is it more complicated to do? If my understanding is correct, this seems like a relatively straightforward change in the PyNEST module to me, which I'd be happy to implement and write some unit tests for.
The text was updated successfully, but these errors were encountered: