You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
As discussed on Discourse, it is possible to improve the SciML stacktraces by storing non-nothing optional values in a named tuple, rather than having highly parameterized structs. Since most of the optional fields in SciML structs end up being set to nothing, using a small named tuple with the non-nothing values significantly cuts down on the length of type signatures.
This idea applies to any struct that contains many optional fields. Here is an example in the spirit of ODEFunction.
struct MyFunction{F,N,T}
f::F
more_funcs::NamedTuple{N,T}endfunctionMyFunction(
f;
mass_matrix=nothing, analytic=nothing, tgrad=nothing,
jac=nothing, jvp=nothing, vjp=nothing, jac_prototype=nothing,
sparsity=nothing, Wfact=nothing, Wfact_t=nothing,
paramjac=nothing, syms=nothing, indepsym=nothing,
paramsyms=nothing, observed=nothing, colorvec=nothing,
sys=nothing
)
# This particular syntax requires Julia 1.7.
kwargs = (;
mass_matrix, analytic, tgrad, jac, jvp, vjp, jac_prototype,
sparsity, Wfact, Wfact_t, paramjac, syms, indepsym, paramsyms,
observed, colorvec, sys
)
more_funcs =NamedTuple(k => v for (k, v) inpairs(kwargs) if v !==nothing)
MyFunction(f, more_funcs)
end
For comparison, here is a type SciMLFunction that is essentially the same as ODEFunction.
And here are two functions foo that operate on a SciMLFunction or MyFunction.
functionfoo(funcs::SciMLFunction, x)
g =isnothing(funcs.jac) ? identity : funcs.jac
h =isnothing(funcs.jvp) ? identity : funcs.jvp
k =isnothing(funcs.vjp) ? identity : funcs.vjp
funcs.f(g(h(k(x))))
endfunctionfoo(funcs::MyFunction, x)
g =get(funcs.more_funcs, :jac, identity)
h =get(funcs.more_funcs, :jvp, identity)
k =get(funcs.more_funcs, :vjp, identity)
funcs.f(g(h(k(x))))
end
Now let's initialize the data structures:
sciml_funcs =SciMLFunction(x -> x +1)
my_funcs =MyFunction(x -> x +1)
Now let's compare the stacktraces generated by foo for the two different types. Here's a screenshot of the stacktrace created by SciMLFunction:
And here's a screenshot of the stacktrace created by MyFunction:
If we compare frame 2 from each stacktrace, we see that the printing of the MyFunction type is much shorter than the printing of the SciMLFunction type. I think it's a considerable improvement.
Implementing this technique across the SciML ecosystem has the potential to significantly reduce the size and complexity of SciML stacktraces.
The text was updated successfully, but these errors were encountered:
CameronBieganek
changed the title
Improve stacktraces by holding non-nothing optional values in a named tuple
Improve stacktraces by storing non-nothing optional values in a named tuple
Mar 23, 2023
I've updated the example implementation of MyFunction in the original post. The constructor now explicitly lists out all the valid keyword arguments, so it will naturally check to ensure the user-provided keyword arguments match the expected arguments.
As discussed on Discourse, it is possible to improve the SciML stacktraces by storing non-
nothing
optional values in a named tuple, rather than having highly parameterized structs. Since most of the optional fields in SciML structs end up being set tonothing
, using a small named tuple with the non-nothing
values significantly cuts down on the length of type signatures.This idea applies to any struct that contains many optional fields. Here is an example in the spirit of
ODEFunction
.For comparison, here is a type
SciMLFunction
that is essentially the same asODEFunction
.And here are two functions
foo
that operate on aSciMLFunction
orMyFunction
.Now let's initialize the data structures:
Now let's compare the stacktraces generated by
foo
for the two different types. Here's a screenshot of the stacktrace created bySciMLFunction
:And here's a screenshot of the stacktrace created by
MyFunction
:If we compare frame 2 from each stacktrace, we see that the printing of the
MyFunction
type is much shorter than the printing of theSciMLFunction
type. I think it's a considerable improvement.Implementing this technique across the SciML ecosystem has the potential to significantly reduce the size and complexity of SciML stacktraces.
The text was updated successfully, but these errors were encountered: