-
-
Notifications
You must be signed in to change notification settings - Fork 101
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: fix remake
for parameters dependent on observed variables
#832
Conversation
p = anydict(k => symbolic_type(v) === NotSymbolic() ? v : symbolic_evaluate(v, p) | ||
for (k, v) in p) | ||
for (k, v) in p | ||
p[k] = symbolic_type(v) === NotSymbolic() ? v : symbolic_evaluate(v, p) | ||
end |
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.
why is this preferred? This would be a slower construction.
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.
Is it? I thought it would be faster since it doesn't create a new dictionary
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.
oh I didn't see that it was extending an old one.
It's still adding elements one by one. That might amortize?
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.
julia> function oop(dict)
return Dict{Any, Any}(k => 2v for (k, v) in dict)
end
julia> function iip(dict)
for (k, v) in dict
dict[k] = 2v
end
end
julia> dict = Dict{Any, Any}(rand() => rand() for _ in 1:10000);
julia> oop(dict); iip(dict);
julia> @be oop(dict)
Benchmark: 25 samples with 1 evaluation
min 2.599 ms (50092 allocs: 1.183 MiB)
median 2.696 ms (50092 allocs: 1.183 MiB)
mean 3.925 ms (50092 allocs: 1.183 MiB, 3.60% gc time)
max 29.143 ms (50092 allocs: 1.183 MiB, 90.08% gc time)
julia> @be iip(dict)
Benchmark: 86 samples with 1 evaluation
min 1.004 ms (20085 allocs: 313.828 KiB)
median 1.052 ms (20085 allocs: 313.828 KiB)
mean 1.140 ms (20085 allocs: 313.828 KiB, 1.77% gc time)
max 5.962 ms (20085 allocs: 313.828 KiB, 81.95% gc time)
In-place seems faster
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.
Okay, that's mainly because the generator isn't optimizing there 😅 . Both are slow, but it's fine.
Thanks for the quick fix! I still think this is likely to lead to silent errors for many users if remake(prob; u0 = [...]) and remake(prob; u0 = [...], p = Dict()) are not equivalent. I strongly suspect most people will just use the former and not even realize they might need to use the latter. (Which as we see currently leads to silent correctness issues.) Is there no way to make the latter the default behavior, or alternatively have a system opt into it? If it is made the default there could be a kwarg to turn it off for more advanced users who know their system doesn't need such behavior (and hence can get better performance avoiding it)? That feels like a safer convention from a correctness perspective. |
Well not quite. It's specifically a non-symbolic remake, There is a use case with optimization where, if an optimizer is choosing new parameters, you want to just |
Can one not detect if they are in the symbolic remake context, and in that case enforce that the two forms are equivalent (modulo an explict kwarg to opt out)? |
That's what we do right now, without the keyword argument to make it explicit. |
Yes, but I’m saying to make passing an empty map equivalent to not passing the kwarg at all. These are different now in the symbolic case. |
That's what we do. That's why |
I think @isaacsas means |
Yes, that is what I am saying should be changed. |
Yes that should definitely by changed. |
Isn't it breaking, though? |
The reason it was implemented this way was (iirc) for the limited cases where symbolic |
This feels like it is a worthwhile reason for a breaking change. |
Yeah but what I mean is, is there even any ODE that is solvable where |
|
oh... that's a bug. It's got to be interpreted as a bug. I can't see someone actually relying on that behavior? |
I mean, it allows you to avoid the overhead of creating the symbolic map, substituting and calling |
But only for ODEs/DAEs. For all other problem types it is a potential bug no? |
Is there no notion of an underlying dependency map that could be tested to decide if " creating the symbolic map, substituting and calling remake_buffer while getting the same solve result because initialization" could be bypassed? |
Again though, it feels like the default here should be the safest option, with ways to opt out for users who know what they are doing and need better performance. |
Yeah this seems to be trying to hard to save a little bit of performance. The |
Why was this merged and released? The Catalyst downstream test failures that appear here are pretty clearly remake related. Several Catalyst test sets are now failing too, see everything I'm having to disable in: SciML/Catalyst.jl#1098 |
That wasn't clear... |
@isaacsas @TorkelE this should fix the
remake
issue you were having with conservation laws.Checklist
contributor guidelines, in particular the SciML Style Guide and
COLPRAC.
Additional context
Add any other context about the problem here.