-
Notifications
You must be signed in to change notification settings - Fork 84
Incremental: (Cheap!) Full Reachability to Prune #713
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
Conversation
|
There are more flaws than I thought: Upon reanalysis everything not in the main thread seems to be pruned away (!?) |
The problem was everyone's favorite thing, hashconsing: I re-lifted only the keys in |
|
I suppose this should also fix the second problem (and the corresponding test) from #647, right? If so, then the test should be cherry-picked here. |
sim642
left a comment
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.
The reason I'm thinking about the init_reachable possibility and simplifications related to it, is to find a solution which minimizes the necessary changes to the postsolvers (and especially the incremental ones in TD3). It's risky to make so big changes here last minute, considering the subtle interactions and bugs in the current version, which has gotten a lot more testing.
src/solvers/td3.ml
Outdated
| (* Tracks dependencies between an unknown and the things it depends on AND has side-effects to *) | ||
| let dep = data.dep in |
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 definition of dep containing unknowns which it has side-effects to can be very misleading because the dep definition in the TD3 paper doesn't include that, or does it?
Couldn't dep just be the inverse of infl, like we have previously had, but just use side_infl for the additional lookups when needed later?
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.
It seems like side-effects are not always recorded into side_infl? Is there some specific reason for that?
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.
Well, before this side_infl was only populated during postsolving for marshaling, but wasn't needed to collect during the solving itself.
Of course that can be changed, but I'm wondering if that's even necessary since leaves (side effect targets with no right-hand sides) themselves don't have warnings, which are emitted during their rhs evaluation. So there shouldn't even be anything to reuse from them in var_messages and rho_write.
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.
None of the tests seem to fail but I am still a bit skeptical about using side_infl: it is explicitly cleared before we start the solver, which strikes me as very odd.
It seems that we would run the risk of removing globals that are only side-effected to from superstable things (but remain reachable) if we remove the things that side-effects are done to from dep (though I could not construct an example thus far).
(* reachability will populate these tables for incremental global restarting *)
HM.clear side_dep;
HM.clear side_infl;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.
Maybe the better solution is to rename dep to uses or something that indicates that these are the unknowns that x reads or has side-effects to?
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.
None of the tests seem to fail but I am still a bit skeptical about using
side_infl: it is explicitly cleared before we start the solver, which strikes me as very odd.
Right, the previous use of side_infl was just for restarting, which is all done before starting the solving itself. So to minimize memory usage and not keep around data during the solving, which will be recollected during postsolving anyway.
It seems that we would run the risk of removing globals that are only side-effected to from superstable things (but remain reachable) if we remove the things that side-effects are done to from
dep(though I could not construct an example thus far).
Hmm, you may have some point here, but if that's indeed a problem, then it's broader than just this PR. Maybe it becomes a problem if at least two incremental changes are made (so there's an intermediate run, which both loads and saves). Then I suppose that might lose the original data and not be able to perform restarting on the final execution correctly?
Since all the testing of incrementality has always been just one change, such an issue has never had a chance to reveal itself. I guess @stilscher's benchmarks that do longer chains of incremental changes might also expose these.
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.
So maybe this sort of structure is needed indeed and uses name with fewer mixup opportunities.
Now I'm wondering if it's even necessary to collect this uses during the actual solving or again just during postsolving. The postsolver sees all the changed/new uses and all the reachable_and_superstable should also remain.
|
Following the suggestions by @sim642 , I have now massively simplified it by passing in the intersection of |
Done |
|
I now went with a solution where we do not add the things that we cause side-effects to to |
That sounds like it should be sufficient. The |
|
Actually, resetting the set in this manner breaks the test case 11/09, so I'd suggest we leave it as currently in this PR for now and merge that. |
Would be good to have a TODO in there somewhere about clearing the sets. Otherwise we'll forget unless we immediately figure it out. |
f106225 to
56d230f
Compare
|
@stilscher: Attention, this contains breaking changes to the config options! |
This implements a cheap form of reachability that works on a set of
depcollected during solving (and heavy-weight reachability).Something that is a bit odd:
xtoy, it still is necessary to record thatxdepends ony, to avoid those globals that only receive side-effects but are never read from being pruned. This has the effect that globals that are only side-effected to do not depend on anything, which I am not quite sure is the right thing here.This stronger form of reachability can then be used to additionally filter warnings and accesses to replay: Only those that are superstable and still reachable need to be replayed.
I tested the performance impact on a small program, and this cheap reachability seems to be a lot cheaper than full reachability, meaning that it hopefully is not too expensive also for larger programs:
There are still three incremental tests that fail, all of which use restarting. I'll try to have a look, but I am not so familiar with it: maybe @sim642 has an idea what could go wrong there?
Closes #710