Skip to content

Conversation

@timholy
Copy link
Member

@timholy timholy commented Aug 6, 2021

This allows one to generate reports on both the callee and caller of an inference trigger.

@timholy
Copy link
Member Author

timholy commented Aug 6, 2021

Demo:

julia> f(c) = sum(c[1])
f (generic function with 1 method)

julia> c = Any[Any[1,2,3]]
1-element Vector{Any}:
 Any[1, 2, 3]

julia> using SnoopCompile
[ Info: Precompiling SnoopCompile [aa65fe97-06da-5843-b5b1-d5d13cad87d2]

julia> tinf = @snoopi_deep f(c)
InferenceTimingNode: 0.032447/0.037888 on Core.Compiler.Timings.ROOT() with 2 direct children

julia> using JET

julia> @report_call f(c)
No errors !
(Any, 0)

julia> itrigs = inference_triggers(tinf)
2-element Vector{InferenceTrigger}:
 Inference triggered to call f(::Vector{Any}) from eval (./boot.jl:373) inlined into REPL.eval_user_input(::Any, ::REPL.REPLBackend) (/home/tim/src/julia-master/usr/share/julia/stdlib/v1.8/REPL/src/REPL.jl:150)
 Inference triggered to call sum(::Vector{Any}) from f (./REPL[1]:1) with specialization f(::Vector{Any})

julia> report_callee(itrigs[1])
No errors !
(Any, 0)

julia> report_callee(itrigs[2])
═════ 1 possible error found ═════
┌ @ reducedim.jl:889 Base.#sum#738(Base.:, Base.pairs(Core.NamedTuple()), #self#, a)
│┌ @ reducedim.jl:889 Base._sum(a, dims)
││┌ @ reducedim.jl:893 Base.#_sum#740(Base.pairs(Core.NamedTuple()), #self#, a, _3)
│││┌ @ reducedim.jl:893 Base._sum(Base.identity, a, Base.:)
││││┌ @ reducedim.jl:894 Base.#_sum#741(Base.pairs(Core.NamedTuple()), #self#, f, a, _4)
│││││┌ @ reducedim.jl:894 Base.mapreduce(f, Base.add_sum, a)
││││││┌ @ reducedim.jl:322 Base.#mapreduce#731(Base.:, Base._InitialValue(), #self#, f, op, A)
│││││││┌ @ reducedim.jl:322 Base._mapreduce_dim(f, op, init, A, dims)
││││││││┌ @ reducedim.jl:330 Base._mapreduce(f, op, Base.IndexStyle(A), A)
│││││││││┌ @ reduce.jl:402 Base.mapreduce_empty_iter(f, op, A, Base.IteratorEltype(A))
││││││││││┌ @ reduce.jl:353 Base.reduce_empty_iter(Base.MappingRF(f, op), itr, ItrEltype)
│││││││││││┌ @ reduce.jl:357 Base.reduce_empty(op, Base.eltype(itr))
││││││││││││┌ @ reduce.jl:331 Base.mapreduce_empty(Base.getproperty(op, :f), Base.getproperty(op, :rf), _)
│││││││││││││┌ @ reduce.jl:345 Base.reduce_empty(op, T)
││││││││││││││┌ @ reduce.jl:322 Base.reduce_empty(Base.+, _)
│││││││││││││││┌ @ reduce.jl:313 Base.zero(_)
││││││││││││││││┌ @ missing.jl:106 Base.throw(Base.MethodError(Base.zero, Core.tuple(Base.Any)))
│││││││││││││││││ MethodError: no method matching zero(::Type{Any})
││││││││││││││││└──────────────────
(Any, 1)

julia> report_caller(itrigs[2])
No errors !
(Any, 0)

CC @aviatesk

I might leave this up long enough for folks to experiment with it before merging. An alternative approach is to split out @snoopi_deep and a small portion of its infrastructure into a new package, ProfileInference.jl, which could then be imported by both SnoopCompile & JET. @aviatesk, I'm perfectly happy with either approach, please let me know what you prefer.

@codecov
Copy link

codecov bot commented Aug 6, 2021

Codecov Report

Merging #253 (0ef71df) into master (2ff6c69) will increase coverage by 0.12%.
The diff coverage is 90.90%.

❗ Current head 0ef71df differs from pull request most recent head 9469a1c. Consider uploading reports for the commit 9469a1c to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##           master     #253      +/-   ##
==========================================
+ Coverage   86.82%   86.95%   +0.12%     
==========================================
  Files          16       16              
  Lines        2012     2023      +11     
==========================================
+ Hits         1747     1759      +12     
+ Misses        265      264       -1     
Impacted Files Coverage Δ
SnoopCompileCore/src/snoopi_deep.jl 92.00% <ø> (ø)
src/SnoopCompile.jl 100.00% <ø> (ø)
src/parcel_snoopi_deep.jl 89.77% <90.90%> (+0.22%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2ff6c69...9469a1c. Read the comment docs.

@aviatesk
Copy link
Member

aviatesk commented Aug 7, 2021

Great ! I think this would be a simple but very nice first step toward analyzing Julia programs using both static/dynamic information.

An alternative approach is to split out @snoopi_deep and a small portion of its infrastructure into a new package, ProfileInference.jl, which could then be imported by both SnoopCompile & JET

Hmm, I'm still not too sure how SnoopCompile and JET want to use "ProfileInference". My naive understanding is, "ProfileInference" (or SnoopCompile if we go with the current approach) will provide user-facing utilities on top of functionalities of SnoopCompile and JET, and so there is no need for those two packages to load "ProfileInference" ?

@timholy
Copy link
Member Author

timholy commented Aug 7, 2021

One option would be possible to extract:

and put it in a standalone package. It might need a few more things, but if you just want to capture the raw data and then write your own handling, that's the minimum. But it seems likely that you'd soon want https://github.com/timholy/SnoopCompile.jl/blob/1abf0a2ae1f64fb8eb93175b9aa7adf16b9530f8/src/parcel_snoopi_deep.jl#L590-L877, and at that point it might make more sense to just have SnoopCompile be a wrapper. It's already a snoop/Cthulhu/AbstractTrees integration package, so this would not be weird.

Anyway, the point is, let me know what you think makes the most sense.

@aviatesk
Copy link
Member

aviatesk commented Aug 9, 2021

Thanks so much for your explanation.

Okay, so to me it seems more natural to have this integration in SnoopCompile. From JET's viewpoint, it's much simpler if it just focuses on its (half-)static analysis feature, while it just makes sense to have external package (SnoopCompile) that combines JET's static analysis and runtime information.
If you think you want to make SnoopCompile focus on "inference timing" tools, then it also makes sense to have a separate package that is dedicated to execute a program with collecting entry points for static analysis, but as far as I understand, SnoopCompile is already such a package that combines both static and runtime information, right ?

Just a random thought, in the long run, we may want another, more automated way to combine static analysis and runtime execution, e.g. we can use JuliaInterpreter/Cassette/compiler-plugin to automatically invoke "static" analysis provided by SnoopCompile/JET/whatsoever in the middle of program execution and collect some information. But also, we know (basically-)interactive inspections like SnoopCompile/Cthulhu are the most accurate and efficient tools we have at this moment.

@timholy timholy merged commit cb12708 into master Jan 23, 2022
@timholy timholy deleted the teh/jet branch January 23, 2022 00:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants