I don't think there's any fundamental reason things can't work as you're 
hoping, I just think they all count as optimizations that have not yet been 
implemented.

--Tim

On Friday, April 24, 2015 11:19:14 AM Mauro wrote:
> >> Well it seems Julia should know that nothing is used from fn!, without
> >> knowing anything about fn!.  That is at least what @code_warntype
> >> suggest (with julia --inline=no).  For
> >> 
> >> function f(ar)
> >> 
> >>     for i=1:n
> >>     
> >>         hh!(ar, i)
> >>     
> >>     end
> >> 
> >> end
> >> 
> >> the loop gives:
> >>       GenSym(1) = $(Expr(:call1, :(top(next)), GenSym(0), :(#s1::Int64)))
> >>       i = $(Expr(:call1, :(top(getfield)), GenSym(1), 1))
> >>       #s1 = $(Expr(:call1, :(top(getfield)), GenSym(1), 2)) # line 71:
> >>       $(Expr(:call1, :hh!, :(ar::Array{Float64,1}), :(i::Int64)))
> >>       3:
> >>       unless $(Expr(:call1, :(top(!)), :($(Expr(:call1, :(top(!)),
> >> :
> >> :($(Expr(:call1, :(top(done)), GenSym(0), :(#s1::Int64))))))))) goto 2
> >> 
> >> For
> >> function g(fn!,ar)
> >> 
> >>     a = 0
> >>     for i=1:n
> >>     
> >>         fn!(ar, i)
> >>     
> >>     end
> >>     a
> >> 
> >> end
> >> 
> >> the loop gives:
> >>       2:
> >>       GenSym(1) = $(Expr(:call1, :(top(next)), GenSym(0), :(#s1::Int64)))
> >>       i = $(Expr(:call1, :(top(getfield)), GenSym(1), 1))
> >>       #s1 = $(Expr(:call1, :(top(getfield)), GenSym(1), 2)) # line 78:
> >>       (fn!::F)(ar::Array{Float64,1},i::Int64)::Any
> > 
> > Wouldn't it (or fn!) need to allocate for this Any here ^
> > 
> > IIUC its fn! that decides if it returns something, and even if the caller
> > doesn't need it, the return value still has to be stored somewhere.
> 
> I think this optimisation should work irrespective of what fn! returns
> by the fact that the value is not used.  This and more seems to happen
> in the first-order function.  Here a version of first-order
> function which calls a function which returns an inferred Any:
> 
> const aa = Any[1]
> hh_ret!(ar,i) = (ar[i] = hh(ar[i]); aa[1])
> 
> function f_ret(ar)
>     a = aa[1]
>     for i=1:n
>         a=hh_ret!(ar, i)
>     end
>     a
> end
> julia> @time f_ret(a);
> elapsed time: 0.259893608 seconds (160 bytes allocated)
> 
> It's still fast and doesn't allocate, even though it uses the value!
> 
> > Maybe fn! does the allocating, but it still happens.
> 
> It's a different story if there is actual allocation in fn!.
> 
> >>       3:
> >>       unless $(Expr(:call1, :(top(!)), :($(Expr(:call1, :(top(!)),
> >> :
> >> :($(Expr(:call1, :(top(done)), GenSym(0), :(#s1::Int64))))))))) goto 2
> >> 
> >> So, at least from my naive viewpoint, it looks like there is no need for
> >> an allocation in this case.  Or is there ever a case when the return
> >> value of fn! would be used?
> >> 
> >> I think this is quite different from the case when the return value of
> >> fn! is used because then, as long as Julia cannot do type inference on
> >> the value of fn!, it cannot know what the type is.
> > 
> > Which is why its ::Any above I guess and my understanding is Any means
> > boxed and allocated on the heap?
> 
> Thanks for indulging me!

Reply via email to