-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Suboptimal performance of captured small unions #31909
Comments
This corresponds to a TODO in the apply_type tfunc: https://github.com/JuliaLang/julia/blob/master/base/compiler/tfuncs.jl#L998. However, I think there is a larger question of whether putting the union on the outside of the closure is really the right thing to do. Perhaps there is a lowering that would allow small unions as the field type for closures. |
I used this to get around it:
|
I watched the JuliaCon talk where @StefanKarpinski mentioned prioritizing making Julia faster for tabular data and I think solving this would be an important step |
As an idea to improve type stability for capturing closures, such as in #31909, I tried this idea of propagating the closure object as a `PartialStruct` whose `fields` include captured variables of which types are (partially) known. By performing const-prop on this `closure::PartialStruct`, we can achieve a certain level of type stability. Specifically, I made some modifications to `abstract_eval_new` to allow creating `PartialStruct` even for `:new` objects that are `!isconcretedispatch` (since `PartialStruct` can now represent abstract elements). I also adjusted `const_prop_argument_heuristic` to perform aggressive constant propagation using such `closure::PartialStruct`. As a result, the following code now achieves type stability: ```julia julia> Base.infer_return_type((Bool,Int,)) do b, y x = b ? 1 : missing inner = y -> x + y return inner(y) end Any # master Union{Missing, Int64} # this commit ``` However, this alone was not enough to fully resolve #31909. The call graph of `map` is extremely complex, and simply applying constant propagation everywhere does not achieve the type safety requested in the issue. Nevertheless this commit alone would still improve type stability for some cases, so I will go ahead and submit it as a PR.
As an idea to improve type stability for capturing closures, such as in #31909, I tried this idea of propagating the closure object as a `PartialStruct` whose `fields` include captured variables of which types are (partially) known. By performing const-prop on this `closure::PartialStruct`, we can achieve a certain level of type stability. Specifically, I made some modifications to `abstract_eval_new` to allow creating `PartialStruct` even for `:new` objects that are `!isconcretedispatch` (since `PartialStruct` can now represent abstract elements). I also adjusted `const_prop_argument_heuristic` to perform aggressive constant propagation using such `closure::PartialStruct`. As a result, the following code now achieves type stability: ```julia julia> Base.infer_return_type((Bool,Int,)) do b, y x = b ? 1 : missing inner = y -> x + y return inner(y) end Any # master Union{Missing, Int64} # this commit ``` However, this alone was not enough to fully resolve #31909. The call graph of `map` is extremely complex, and simply applying constant propagation everywhere does not achieve the type safety requested in the issue. Nevertheless this commit alone would still improve type stability for some cases, so I will go ahead and submit it as a PR.
As an idea to improve type stability for capturing closures, such as in #31909, I tried this idea of propagating the closure object as a `PartialStruct` whose `fields` include captured variables of which types are (partially) known. By performing const-prop on this `closure::PartialStruct`, we can achieve a certain level of type stability. Specifically, I made some modifications to `abstract_eval_new` to allow creating `PartialStruct` even for `:new` objects that are `!isconcretedispatch` (since `PartialStruct` can now represent abstract elements). I also adjusted `const_prop_argument_heuristic` to perform aggressive constant propagation using such `closure::PartialStruct`. As a result, the following code now achieves type stability: ```julia julia> Base.infer_return_type((Bool,Int,)) do b, y x = b ? 1 : missing inner = y -> x + y return inner(y) end Any # master Union{Missing, Int64} # this commit ``` However, this alone was not enough to fully resolve #31909. The call graph of `map` is extremely complex, and simply applying constant propagation everywhere does not achieve the type safety requested in the issue. Nevertheless this commit alone would still improve type stability for some cases, so I will go ahead and submit it as a PR.
This is an alternative to #56532 and can resolve #31909. Currently `apply_type_tfunc` is unable to handle `Union`-argtypes with any precision. With this change, `apply_type_tfunc` now performs union-splitting on `Union`-argtypes and returns the merged result of the splits. While this can improve inference precision, we might need to be cautious about potential inference time bloat.
This is an alternative to #56532 and can resolve #31909. Currently `apply_type_tfunc` is unable to handle `Union`-argtypes with any precision. With this change, `apply_type_tfunc` now performs union-splitting on `Union`-argtypes and returns the merged result of the splits. While this can improve inference precision, we might need to be cautious about potential inference time bloat.
This is an alternative to #56532 and can resolve #31909. Currently `apply_type_tfunc` is unable to handle `Union`-argtypes with any precision. With this change, `apply_type_tfunc` now performs union-splitting on `Union`-argtypes and returns the merged result of the splits. While this can improve inference precision, we might need to be cautious about potential inference time bloat.
This is an alternative to #56532 and can resolve #31909. Currently `apply_type_tfunc` is unable to handle `Union`-argtypes with any precision. With this change, `apply_type_tfunc` now performs union-splitting on `Union`-argtypes and returns the merged result of the splits. While this can improve inference precision, we might need to be cautious about potential inference time bloat.
This is an alternative to #56532 and can resolve #31909. Currently `apply_type_tfunc` is unable to handle `Union`-argtypes with any precision. With this change, `apply_type_tfunc` now performs union-splitting on `Union`-argtypes and returns the merged result of the splits. While this can improve inference precision, we might need to be cautious about potential inference time bloat.
This is an alternative to #56532 and can resolve #31909. Currently `apply_type_tfunc` is unable to handle `Union`-argtypes with any precision. With this change, `apply_type_tfunc` now performs union-splitting on `Union`-argtypes and returns the merged result of the splits. While this can improve inference precision, we might need to be cautious about potential inference time bloat.
As an idea to improve type stability for capturing closures, such as in #31909, I tried this idea of propagating the closure object as a `PartialStruct` whose `fields` include captured variables of which types are (partially) known. By performing const-prop on this `closure::PartialStruct`, we can achieve a certain level of type stability. Specifically, I made some modifications to `abstract_eval_new` to allow creating `PartialStruct` even for `:new` objects that are `!isconcretedispatch` (since `PartialStruct` can now represent abstract elements). I also adjusted `const_prop_argument_heuristic` to perform aggressive constant propagation using such `closure::PartialStruct`. As a result, the following code now achieves type stability: ```julia julia> Base.infer_return_type((Bool,Int,)) do b, y x = b ? 1 : missing inner = y -> x + y return inner(y) end Any # master Union{Missing, Int64} # this commit ``` However, this alone was not enough to fully resolve #31909. The call graph of `map` is extremely complex, and simply applying constant propagation everywhere does not achieve the type safety requested in the issue. Nevertheless this commit alone would still improve type stability for some cases, so I will go ahead and submit it as a PR.
The text was updated successfully, but these errors were encountered: