-
Notifications
You must be signed in to change notification settings - Fork 15
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
clarify: calling prepared with different x type #633
Comments
The documentation in https://juliadiff.org/DifferentiationInterface.jl/DifferentiationInterface/stable/explanation/operators/#Reusing-preparation gives necessary conditions for preparation to be reusable. Therefore, if you step outside of these conditions, nothing at all is guaranteed. Depending on 1) the backend 2) the specific operator 3) the function to differentiate and 4) the argument types, DI may execute without error or throw an error. I can't spontaneously imagine a situation where it would silently return the wrong result but I can't definitively exclude it. |
Thanks for the clairification. Yes, I will make a PR, to the effect "don't do that". |
Thinking about this, I am wondering it it would be feasible to expose a function that tries to convert the argument to the type accepted by a prepared operation. For backends that don't care it would be a no-op, for eg ForwardDiff it would convert to the element type obtained from the tag type. |
I have thought about it, or more precisely I have thought about checking that the types match and throwing an error if they don't. But it would require a systematic overhaul of every single preparation type to store the function signature it was prepared with (because most backends don't care and so they don't record it natively). It's completely feasible but rather tedious |
Again, for those backends I would make it a no-op. |
An automatic conversion utility would mean that we're voluntarily making efforts to support this functionality, which can never be part of the API because some backends are very strict on the types they accept and automatic conversion has its limits. So I would rather error right away than implicitly support this for some backends while it may not work with others? |
I am thinking of a "best effort" solution, eg something along the lines of value_and_gradient(f, prep, backend, convert_argument(prep, backend, x)) where for most backends (which take everything that makes sense) we would have convert_argument(prep, backend, x) = x If Generally, the reason for this is that I like to write code following the robustness principle, ie accept all kinds of inputs that make sense. |
On the other hand, you could argue that these implicit conversions lead to hidden performance pitfalls, which may be a no-go for performance users. As far as AD systems are concerned, one could say that Zygote follows this robustness principle while Enzyme and Mooncake are much more strict in terms of types, and also much more performant. For those backends, adding an implicit conversion if a user happens to pass the wrong array type seems worse than just letting it error? |
Presicely, I fully agree. Which is why I was not proposing an implicit conversion API, but an explicit one: the caller opts in by using |
Oh right, I see now, sorry. How would this handle context arguments? And tangents? |
I would have to look into the implementation to answer that, I am not yet familiar with all the details. |
From the docs it is not clear what happens if the user prepares with a given type of
x
, then calls with another type. EgIn practice, it seems to work in the example above and with all backend types I tried. But what does the API guarantee? Some possibilities:
The text was updated successfully, but these errors were encountered: