Thanks, this is all very useful. I think I am going to back away from using 
the @anon functions at the moment, so I'll postpone my idea to encapsulate 
the functions into a type. Instead, I will just pass a parameter type to an 
externally defined(not nested) function. I had thought this would be slow 
(see my question here 
https://groups.google.com/forum/#!topic/julia-users/6U-otLSx7B0 ), but I 
did a little testing.

immutable UtilityFunction
    sigmac::Float64
    sigmal::Float64
    psi::Float64
end
function u(UF::UtilityFunction,consump,labor)
    sigmac = UF.sigmac    
    sigmal = UF.sigmal    
    psi = UF.psi    
    consump.^(1-sigmac)/(1-sigmac) + psi*(1-labor).^(1-sigmal)/(1-sigmal)
end
function u4(consump,labor)  
    consump.^(1-4)/(1-4) + 1*(1-labor).^(1-2)/(1-2)
end

function test1(UF)
    for i = 1:1000000
        u4(1. + 1/i, .5)
    end
end
function test2(UF)
    for i = 1:1000000
        u(UF,1. + 1/i ,.5)
    end
end
UF = UtilityFunction(4,2,1)

@time test1(UF)
@time test2(UF)

elapsed time: 0.068562617 seconds (80 bytes allocated)
elapsed time: 0.139422608 seconds (80 bytes allocated)


 So, even versus the extreme case where I built the constants into the 
function, the slowdown is not huge. I asume @anon would have similar 
performance to the constants built in case, which is nice. However, I want 
to be able to share my Julia code with others who aren't very experienced 
with the language, so I'd be uncomfortable asking them to understand the 
workings of FastAnonymous. It's useful to know about in case I need the 
speedup in my own personal code though.

On Tuesday, June 23, 2015 at 8:51:25 AM UTC-4, [email protected] wrote:
>
> Yes, this proves to be an issue for me sometimes too. I asked a 
> StackOverflow question on this topic a few months ago and got a very 
> interesting response, as well as some interesting links. See here:
>
>
> http://stackoverflow.com/questions/28356437/julia-compiler-does-not-appear-to-optimize-when-a-function-is-passed-a-function
>
> As a general rule, if the function you are passing round is very simple 
> and gets called a lot, then you will really notice the performance 
> overhead. In other cases where the function is more complicated, or is not 
> called that often, the overhead will be barely measurable.
>
> If the number of functions that you want to pass around is not that large, 
> one way around this is to use types and multiple dispatch instead of 
> functions, eg
>
> abstract UtilityFunctions
> type QuadraticUtility <: UtilityFunctions
>     a::Float64
>     b::Float64
>     c::Float64
> end
> evaluate(x::Number, f::QuadraticUtility) = f.a*x^2 + f.b*x + f.c
>
> Now your function would be something like:
>
> function solveModel(f::UtilityFunctions, ...)
>
> and you would call evaluate at the appropriate place in the function body 
> and multiple dispatch will take care of the rest. There is no performance 
> overhead with this approach.
>
> Of course, if you want to be able to just pass in any arbitrary function 
> that a user might think up, then this approach is not tenable.
>
> On Tuesday, 23 June 2015 01:07:25 UTC+10, Andrew wrote:
>>
>>
>>
>> I'm trying to write some abstract Julia code to solve a variety of 
>> economics models. Julia provides powerful abstraction tools which I think 
>> makes it very well-suited to this; however, I've read in several places 
>> that Julia doesn't yet know how to inline functions passed as arguments, 
>> hence code like
>>
>> function SolveModel(Utility::Function, ProductionTechnology::Function
>> ,...)
>> ...
>>
>> will be slow. I performed this very simple test.
>>
>> function ftest1()
>>     u(x) = log(x)
>>     function hello(fun::Function)
>>         for i = 1:1000000
>>             fun(i.^(1/2))
>>         end
>>     end
>> end
>>     
>> function ftest2()
>>     function hello()
>>         for i = 1:1000000
>>             log(i.^(1/2))
>>         end
>>     end
>> end
>>
>> @time ftest1()
>> @time ftest2()
>>
>> elapsed time: 6.065e-6 seconds (496 bytes allocated)
>> elapsed time: 3.784e-6 seconds (264 bytes allocated)
>>
>>
>>  The inlined version is about twice as fast, which isn't all that bad, 
>> although I'm not sure if it would be worse in a more complicated example. 
>> Perhaps I shouldn't worry about this, and should code how I want. I was 
>> wondering though, if anybody knows when this is going to change. I've read 
>> about functors, which I don't really understand, but it sounds like people 
>> are working on this problem.
>>
>

Reply via email to