Skip to content
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

Put inference parameters in a dedicated object #18496

Merged
merged 1 commit into from
Oct 19, 2016
Merged

Conversation

maleadt
Copy link
Member

@maleadt maleadt commented Sep 13, 2016

Part of #18338, based on #18396 for now because it uses kwargs in inference.

Entry-point function parameters to type inference (needtree, optimize, cached) are now saved in the InferenceState, which makes them available in more places. However, using cached that way breaks abstract_call_gf_by_type. Any reason this should always be saving its results?

Performance difference in loading base/inference.jl seems undetectable. Suggestions for better testing of type inference performance?

cc @JeffBezanson @vtjnash

@maleadt maleadt added the compiler:inference Type inference label Sep 13, 2016
@StefanKarpinski StefanKarpinski added this to the 0.6.0 milestone Sep 14, 2016
@JeffBezanson
Copy link
Member

Good tests of inference performance are the sys.so build, and some of the longer-running test suites like subarray.

cached::Bool

# parameters limiting potentially-infinite types
MAX_TYPEUNION_LEN::Int
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just keep all of these as global constants unless you have a use case for changing them on some calls.

@JeffBezanson
Copy link
Member

I don't really like that this makes a whole bunch of simple pure functions depend on an extra parameter that they usually don't use.

@JeffBezanson
Copy link
Member

However, using cached that way breaks abstract_call_gf_by_type. Any reason this should always be saving its results?

The only reason we currently pass cached=false is to look at a single function e.g. without inlining. Any other functions recursively inferred during that process can still be optimized and cached as normal. In fact it is important not to propagate the parameters passed to inference, or we can end up caching non-optimized versions of functions. For example if I want to see the IR for f() = 1+1 without inlining, we will end up inferring +(::Int,::Int) in the process, so we might as well save the result. The cache also prevents recursive functions from being inferred infinitely.

@maleadt
Copy link
Member Author

maleadt commented Sep 14, 2016

I don't really like that this makes a whole bunch of simple pure functions depend on an extra parameter that they usually don't use.

I agree, but I felt like keeping some const and others configurable was a half-assed job. I'll try to strike a better balance, IIRC most of the diff is caused byMAX_TUPLETYPE_LEN and MAX_TYPE_DEPTH anyway.

The cache also prevents recursive functions from being inferred infinitely.

Right, didn't realize this, that explains the hang.

In fact it is important not to propagate the parameters passed to inference, or we can end up caching non-optimized versions of functions.

OK, so I've changed that behavior in this PR, propagating all parameters but not caching the result instead.

The reason I wanted to propagate parameters for an entire inference "cycle", is because of the hooks I'm testing in #18338. Replacing a call applies to every function in a cycle, not only the top one. By propagating all parameters, including cached, we avoid re-using or polluting anything in the cache (except that it breaks recursion handling). This also side-steps the issue of needing multiple caches.

@maleadt maleadt force-pushed the tb/inference_params branch 3 times, most recently from 59c365c to 6f45396 Compare October 12, 2016 18:53
@maleadt
Copy link
Member Author

maleadt commented Oct 12, 2016

Updated and rebased.

EDIT: also, no performance difference running subarray test.

I would still like to change the caching behavior, where inferring with cached=false adds called functions to the cache in order to break recursion. I don't fully grok the interplay between inference & the method tables, so any suggestions on how to do this @JeffBezanson @vtjnash?

@@ -3951,10 +3980,13 @@ function reindex_labels!(sv::InferenceState)
end
end

function return_type(f::ANY, t::ANY)
function return_type(f::ANY, t::ANY, params::InferenceParams=InferenceParams())
# TODO: are all local calls to return_type processed by pure_eval_call?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no

@@ -1590,7 +1618,7 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, caller
end
end
end
frame = typeinf_frame(code, true, true, caller)
frame = typeinf_frame(code, caller, InferenceParams(caller.params; cached=true))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a hot path, it would be nice to avoid the kwargs dispatch and allocation here

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, removed.

@vtjnash
Copy link
Member

vtjnash commented Oct 12, 2016

Can we leave out cached for now? I'll try to help you with making a selectable cache, but for now, I'm concerned it will just make #17057 trickier for me, since we're already overloading its meaning somewhat.

@maleadt
Copy link
Member Author

maleadt commented Oct 12, 2016

Yeah sure, I almost did already but left it in not knowing what a better solution would look like.
Dropping cached also obviates the need for the ugly kwarg copy ctor.

I can also maintain this PR until after #17057, if you like.

@vtjnash
Copy link
Member

vtjnash commented Oct 12, 2016

the rest of it shouldn't conflict (other than superficially, and I already know I'll have to deal with rebasing other stuff anyways)

@maleadt maleadt force-pushed the tb/inference_params branch 2 times, most recently from 7048bc4 to a19f415 Compare October 12, 2016 21:17
@maleadt
Copy link
Member Author

maleadt commented Oct 12, 2016

I've also left out optimize, because without proper caching (or copying-and-modifying the InferenceParams when passing down) a nonoptimized method could end up in the cache.

# reasonable defaults
InferenceParams(;inlining::Bool=inlining_enabled(),
tupletype_len::Int=15, tuple_depth::Int=16,
tuple_splat::Int=4, union_splitting::Int=4) =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is swapping the defaults for depth and splat

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's bad. Nicely spotted, fixed.

@maleadt maleadt force-pushed the tb/inference_params branch 2 times, most recently from 73f3de3 to 56e8b60 Compare October 17, 2016 14:04
This allows overriding parameters, while reducing global state
and simplifying the API.
@maleadt maleadt merged commit d80ad6e into master Oct 19, 2016
@tkelman tkelman deleted the tb/inference_params branch October 19, 2016 12:13
@JeffBezanson
Copy link
Member

Is there a particular reason those 4 globals were moved into the struct, and the other 2 were kept global?

@maleadt
Copy link
Member Author

maleadt commented Oct 20, 2016

I initially put them all in the struct, but that caused too much churn (as you mentioned above, making a whole bunch of simple pure functions depend on an extra parameter). So I took the ones causing the largest diff out.

@andyferris
Copy link
Member

Out of curiosity, when we say "configurable" is e.g. MAX_TUPLE_SPLAT something I can specify on startup, when building a system image, or at the REPL?

@maleadt
Copy link
Member Author

maleadt commented Apr 26, 2017

@andyferris: no, apart from changing the default value in inference.jl, or when calling into inference yourself (eg. this demo).

@andyferris
Copy link
Member

Ok - thanks @maleadt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler:inference Type inference
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants