-
Notifications
You must be signed in to change notification settings - Fork 175
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
Custom solver without default args will break cache #1054
Comments
Also... there is a slight inherent problem with developing a custom solver when the cache is enabled: changing the method's implementation won't change the fingerprint (unless the attributes are changed as well). This means that someone trying to write their own solver might be confused when they keep getting the same results, despite changing their code. This could also be hazardous with Nengo solvers if, say, a bugfix was made to one of the solvers. The cache would not pick up on the fix and continue using the previous incorrect results. Perhaps cache misses should be forced when the solver is not within the Nengo directory (to alleviate the first problem), and the Nengo Obviously this is hard problem in general, since it's always possible to construct weird counter-examples, but I think we should aim to be slightly less aggressive with how we detect hits, since false-hits are way more "costly" in terms of user time than false-misses. Also a way to force cache misses on specific connections (#1044) would be nice when all else fails. This might be necessary if the custom solver has attributes that are not picklable (e.g. a lambda function). Edit: Some sort of flag on the solver would also solve this (see discussion below). |
This is a general problem with caches and development, and unfortunately I don't think there's much we could do about it. I guess we could have the cache disabled by default in the development version. Either way, I think it's good to make developers aware that the cache is there, and perhaps recommend developing with the cache off.
This is more worrying, but I think something like you suggested (incorporating the version in some way), should address it. Do we not do that right now? My inclination is that we should always be clearing cache files that don't match the current version, but I'm not sure how difficult that is. Actually, we should probably have the cache files organized with separate folders for each version. |
Oh, that's a really good point. Would there be any way for users to turn the cache on for their own solver, though? EDIT: also, I wouldn't call them cache misses, I would just say don't check the cache at all. |
There could be a flag that solvers have to explicitly set to |
I wonder if we could automatically make a solver "version" with inspect. Could be a bit magic and fragile, though. |
I'm not necessarily advocating the following view, but if we don't trust our users then by default it should be disabled for their own solvers, even if their code hasn't changed at all. Because in extreme cases they may be manipulating global variables or even files outside the scope of the fingerprint. We can trust our own code enough to know this won't happen, but if the solver is outside the Nengo directory who knows... |
To solve this we could add the possibility for classes to implement a special method to overwrite how the fingerprint is created. This is similar to other things in Python like pickles where there is a default, but classes can implement
Regarding the original issue in the first post. I would argue that this should actually fail:
The questions are:
|
probably only if we access the code object which seems too fragile and not portable enough to me |
For the second set of questions, it could skip the cache and spew a warning that links to the relevant documentation/issue? Also it's still not immediately obvious to me why you need to know the defaults. Couldn't there be special |
If the defaults change, it could lead to loading wrong results. But that's sort of a problem we already have (but it might be even easier to overlook in this case). Also, the code has to be rewritten to not pass in |
The conclusions from the dev meeting seem to be:
|
Addresses #1054. Code can change and we can't detect it, so we allow only things that are marked as supporting fingerprints to be cached and only mark objects that should be stable as supporting this. Note that an object marked as supporting fingerprints will retain this mark even if it references objects that are not marked as supporting fingerprints (because the fingerprint is created by pickling and we cannot hook into that process). This also removes the solver_fn from the fingerprint because it is not needed in there. It should always be the same function which is part of the builder (the solver itself is still part of the fingerprint of course). This in turn allows to simplify the SolverMock in the test code a little bit. (It actually is slightly misnamed as it mocks the solver_fn and not a Solver.)
Addresses #1054. Code can change and we can't detect it, so we allow only things that are marked as supporting fingerprints to be cached and only mark objects that should be stable as supporting this. Note that an object marked as supporting fingerprints will retain this mark even if it references objects that are not marked as supporting fingerprints (because the fingerprint is created by pickling and we cannot hook into that process). This also removes the solver_fn from the fingerprint because it is not needed in there. It should always be the same function which is part of the builder (the solver itself is still part of the fingerprint of course). This in turn allows to simplify the SolverMock in the test code a little bit. (It actually is slightly misnamed as it mocks the solver_fn and not a Solver.)
PR #1066 ensures that decoders for custom solvers (and neuron types!) are only cached when marked as supporting this. This doesn't solve the original issue, but it seems the consens from the dev meeting was to require the use of |
Addresses #1054. Code can change and we can't detect it, so we allow only things that are marked as supporting fingerprints to be cached and only mark objects that should be stable as supporting this. Note that an object marked as supporting fingerprints will retain this mark even if it references objects that are not marked as supporting fingerprints (because the fingerprint is created by pickling and we cannot hook into that process). This also removes the solver_fn from the fingerprint because it is not needed in there. It should always be the same function which is part of the builder (the solver itself is still part of the fingerprint of course). This in turn allows to simplify the SolverMock in the test code a little bit. (It actually is slightly misnamed as it mocks the solver_fn and not a Solver.)
Addresses #1054. Code can change and we can't detect it, so we allow only things that are marked as supporting fingerprints to be cached and only mark objects that should be stable as supporting this. This also removes the solver_fn from the fingerprint because it is not needed in there. It should always be the same function which is part of the builder (the solver itself is still part of the fingerprint of course). This in turn allows to simplify the SolverMock in the test code a little bit. (It actually is slightly misnamed as it mocks the solver_fn and not a Solver.) Co-authored by: Jan Gosmann <jgosmann@uwaterloo.ca> Co-authored by: Daniel Rasmussen <daniel.rasmussen@appliedbrainresearch.com>
Fixed in #1068 |
This gives the following error:
Changing the signature to
(self, A, Y, rng=None, E=None)
resolves this issue.The text was updated successfully, but these errors were encountered: