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

Remove recursion through @generated #9

Open
tveldhui opened this issue Jan 25, 2019 · 0 comments
Open

Remove recursion through @generated #9

tveldhui opened this issue Jan 25, 2019 · 0 comments
Assignees

Comments

@tveldhui
Copy link
Contributor

tveldhui commented Jan 25, 2019

I tracked down a per-row allocation in the FSM join TPC-H Q1 to a call to unsafe_load!(::Date) that was not type stable. The issue was that unsafe_load! is a @generated function that calls itself recursively, and Julia does not appear to make any guarantees about type inference in this scenario.

Here is an example that demonstrates the issue:

@generated function foo(::Val{N}) where N                                                   
   if N < 1                                                                                 
      :(1)                                                                              
   else                                                                                     
      # Return 1+foo(Val(N-1)), but using Int(N) for even
      # and Float64(N) for odd            
      if N % 2 == 0                                                                         
         :(1+foo(Val(Int(N)-1)))                                                                                                                                       
      else                                                                                  
         :(1+foo(Val(Float64(N)-1)))                                                                                                                                    
      end                                                                                   
   end                                                                                      
end

If you start a new julia 1.0.1 session, paste in the above definition, and then try these calls, you’ll get type stable code:

julia> @code_typed foo(Val(2))
CodeInfo(
2 1 ─     (Base.sub_float)(1.0, 1.0)::Float64                                                     
  └──     return 3                                                                            
) => Int64

julia> @code_typed foo(Val(3))
CodeInfo(
2 1 ─     (Base.sub_float)(3.0, 1.0)::Float64                                                     
  │       (Base.sub_float)(1.0, 1.0)::Float64                                                     
  └──     return 4                                                                            
) => Int64

julia> @code_typed foo(Val(4))
CodeInfo(
2 1 ─     (Base.sub_float)(3.0, 1.0)::Float64                                                     
  │       (Base.sub_float)(1.0, 1.0)::Float64                                                     
  └──     return 5                                                                            
) => Int64

However, if you restart julia, paste in the definition of foo(), and immediately try foo(Val(4)), it will produce unstable code:

julia> @code_typed foo(Val(4))
CodeInfo(
2 1 ─ %1 = invoke Main.foo($(QuoteNode(Val{3}()))::Val{3})::Any                                   
  │   %2 = (1 + %1)::Any                                                                          
  └──      return %2                                                                          
) => Any

It’s the same call as before, but without the previous calls to foo(Val(3)) and foo(Val(2)) in the cache, the result of type inference is different.

In the case of unsafe_load!(::Blob{Date}), there was a recursion from unsafe_load!(::Blob{Date}) to unsafe_load!(::Blob{UTInstant{Day}}) to unsafe_load!(::Blob{Day}) to unsafe_load!(::Int64), and type inference was failing, resulting in an ::Any type:

screen shot 2019-01-24 at 1 15 30 pm

@tveldhui tveldhui self-assigned this Jan 25, 2019
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

No branches or pull requests

1 participant