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

optimization of "pass-through" varargs methods #5

Closed
jrevels opened this issue Sep 5, 2017 · 3 comments
Closed

optimization of "pass-through" varargs methods #5

jrevels opened this issue Sep 5, 2017 · 3 comments

Comments

@jrevels
Copy link
Collaborator

jrevels commented Sep 5, 2017

Cassette relies heavily on varargs functions to pass through arguments with "no" overhead; until JuliaLang/julia#5402 is fixed, the performance of contextual code execution will be trash.

@jrevels jrevels changed the title upstream issue: JuliaLang/julia#5402 upstream perf issue: JuliaLang/julia#5402 Oct 11, 2017
@jrevels jrevels changed the title upstream perf issue: JuliaLang/julia#5402 JuliaLang/julia#5402 Oct 11, 2017
@jrevels jrevels changed the title JuliaLang/julia#5402 optimization of "pass-through" varargs methods Oct 11, 2017
@JeffBezanson
Copy link

A workaround for now is to add extra methods to cause specialization, e.g.

f(args...) = # actual code

f(a) = invoke(f, Tuple{Vararg{Any}}, a,)
f(a, b) = invoke(f, Tuple{Vararg{Any}}, a, b)
f(a, b, c) = invoke(f, Tuple{Vararg{Any}}, a, b, c)
...

@jrevels
Copy link
Collaborator Author

jrevels commented Nov 2, 2017

Thanks, trying this out now. Two questions:

  1. How does this workaround interact with inlining? Can things get inlined through invoke or is invoke a de facto inline barrier? From some cursory exploration, it looks like invoke is not an inline barrier. Cassette forcibly inlines a lot of stuff, with the hopes that eventual no-op transformations are elided in generated code (in many use cases, "most" of Cassette's transformations end up being no-ops/pass-throughs).

  2. It seems that I'm running into a cycle when implementing this workaround for one of Cassette's callable structs. Here's a MWE:

julia> struct Foo{X,F}
           x::X
           f::F
       end

julia> (foo::Foo{Int})(args...) = foo.f(args...)

julia> (foo::Foo{Int})(x) = invoke(foo, Tuple{Vararg{Any}}, x)

julia> Foo(1, sin)(1)
ERROR: StackOverflowError:
Stacktrace:
 [1] (::Foo{Int64,typeof(sin)})(::Int64) at ./REPL[3]:0
 [2] (::Foo{Int64,typeof(sin)})(::Int64) at ./REPL[3]:1 (repeats 26666 times)

EDIT: Furthermore:

julia> struct Foo{F}
           x
           f::F
       end

julia> (foo::Foo)(args...) = foo.f(args...)

julia> (foo::Foo)(a) = invoke(foo, Tuple{Vararg{Any}}, a)

julia> @code_typed Foo(1, sin)(1)^C

julia> Foo(1, sin)(1)
[1]    52977 segmentation fault  julia7

Weirdly, the bug goes away if we get rid of the x field, but that field is actually necessary in the real code. What should I be doing here instead?

@jrevels
Copy link
Collaborator Author

jrevels commented May 10, 2018

closed by #41

@jrevels jrevels closed this as completed May 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants