Skip to content

Make EvalFunc hold world age and deprecate GeneralizedGenerated #560

@ChrisRackauckas

Description

@ChrisRackauckas

@c42f's PR JuliaLang/julia#35844 gives an invoke_in_world that we could use to replace how we've currently been using GeneralizedGenerated in a way that is safer for general Julia code. Currently our build_function has two routes: one that uses eval and generates an EvalFunc, and the other which builds the function via GeneralizedGenerated. The eval version had to be created because the type from GeneralizedGenerated can break. If you have a million equations, you get a gigantic type and that just seems to do some outrageous unholy things to the compiler.

EvalFunc requires one to invoke in the latest, so the machinery is defined in DiffEqBase so that we have

https://github.com/SciML/DiffEqBase.jl/blob/master/src/solve.jl#L5-L8

and then https://github.com/SciML/DiffEqBase.jl/blob/master/src/solve.jl#L30 which basically gives us a hook to get around world age issues when GeneralizedGenerated is not used. This works but has all of the downsides of invokelatest.

However, this new invoke is definitely a good way forward. For example, when we generate the functions from the symbolic code, i.e. https://github.com/SciML/ModelingToolkit.jl/blob/master/src/systems/diffeqs/abstractodesystem.jl#L122-L152, instead of building just an EvalFunc, we can make a WorldFunc that capturers the WorldAge as type information. Then we can have a call on this object perform invoke_in_world at the right world age. Hopefully, storing the world age as type information will make this all inferred and just as fast as a standard Julia function? (that's a question for @c42f).

With this in place, we can remove GeneralizedGenerated usage because then the standard function would be safe due to invoking in the proper world. The only issue that would come up is then that this is not precompile safe because the generated code is made for a specific world. However, any function that is made to precompile is a function evaluated in a module scope, which means it's safe to just use eval and not invoke in the world, and so we just need a flag to turn off the WorldFunc wrapping. That should make the whole symbolic system generate functions that are both efficient and don't have world age issues, and not have the scaling issues of GG.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions