Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
Thanks. Cool ideas! P On Thursday, January 15, 2015 at 12:08:05 PM UTC-8, Mauro wrote: > > Have you read this recent thread and its examples? > https://groups.google.com/d/msg/julia-dev/JEiH96ofclY/_amm9Cah6YAJ > > M > > On Thu, 2015-01-15 at 20:50, Petr Krysl > > wrote: > > So the "call" syntax on a type works, but using the implementation > > referenced above, it is SLOW. > > > > # Slow, function callback > > function test1(f, n) > > summ=0 > > for i=1:n > > summ=summ+f(i) > > end > > return summ > > end > > > > g(i::Int)=i > > > > # Fast, hardwired function g() > > function test2(n) > > summ=0 > > for i=1:n > > summ=summ+g(i) > > end > > return summ > > end > > > > # Fast, using method defined for an object > > function test4{T}(o::T, n) > > summ=0 > > for i=1:n > > summ=summ+get(o,i) > > end > > return summ > > end > > > > type MyFun1 > > end > > function get(o::MyFun1,i::Int) > > return g(i) > > end > > > > # Slow, using "call" on a singleton > > type MyFun3 end > > call(::Type{MyFun3},i::Int)=g(i)::Int > > > > n=10002345; > > @time println("test1(g, n) = $( test1(g, n) )") > > @time println("test2(n) = $( test2(n) )") > > @time println("test4(MyFun1(), n) = $( test4(MyFun1(), n) )") > > @time println("test1(MyFun3, n) = $( test1(MyFun3, n) )") > > > > julia> include("fun.jl") > > test1(g, n) = 50023457750685 > > elapsed time: 0.610016329 seconds (480173520 bytes allocated, 27.80% gc > > time) > > test2(n) = 50023457750685 > > elapsed time: 0.003086749 seconds (75304 bytes allocated) > > test4(MyFun1(), n) = 50023457750685 > > elapsed time: 0.004098207 seconds (90436 bytes allocated) > > test1(MyFun3, n) = 50023457750685 > > elapsed time: 0.665630908 seconds (480184232 bytes allocated, 23.21% gc > > time) > >
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
Aha: # Fast, got to declare the object! function test5{T}(o::Type{T}, n) summ=0 for i=1:n summ=summ+o(i) end return summ end julia> include("fun.jl") test1(g, n) = 50023457750685 elapsed time: 0.619951473 seconds (480173520 bytes allocated, 27.32% gc time) test2(n) = 50023457750685 elapsed time: 0.002951912 seconds (75304 bytes allocated) test4(MyFun1(), n) = 50023457750685 elapsed time: 0.003362795 seconds (90436 bytes allocated) test1(MyFun3, n) = 50023457750685 elapsed time: 0.661085013 seconds (480184232 bytes allocated, 23.39% gc time) test5(MyFun3, n) = 50023457750685 elapsed time: 0.003583276 seconds (116768 bytes allocated)
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
Have you read this recent thread and its examples? https://groups.google.com/d/msg/julia-dev/JEiH96ofclY/_amm9Cah6YAJ M On Thu, 2015-01-15 at 20:50, Petr Krysl wrote: > So the "call" syntax on a type works, but using the implementation > referenced above, it is SLOW. > > # Slow, function callback > function test1(f, n) > summ=0 > for i=1:n > summ=summ+f(i) > end > return summ > end > > g(i::Int)=i > > # Fast, hardwired function g() > function test2(n) > summ=0 > for i=1:n > summ=summ+g(i) > end > return summ > end > > # Fast, using method defined for an object > function test4{T}(o::T, n) > summ=0 > for i=1:n > summ=summ+get(o,i) > end > return summ > end > > type MyFun1 > end > function get(o::MyFun1,i::Int) > return g(i) > end > > # Slow, using "call" on a singleton > type MyFun3 end > call(::Type{MyFun3},i::Int)=g(i)::Int > > n=10002345; > @time println("test1(g, n) = $( test1(g, n) )") > @time println("test2(n) = $( test2(n) )") > @time println("test4(MyFun1(), n) = $( test4(MyFun1(), n) )") > @time println("test1(MyFun3, n) = $( test1(MyFun3, n) )") > > julia> include("fun.jl") > test1(g, n) = 50023457750685 > elapsed time: 0.610016329 seconds (480173520 bytes allocated, 27.80% gc > time) > test2(n) = 50023457750685 > elapsed time: 0.003086749 seconds (75304 bytes allocated) > test4(MyFun1(), n) = 50023457750685 > elapsed time: 0.004098207 seconds (90436 bytes allocated) > test1(MyFun3, n) = 50023457750685 > elapsed time: 0.665630908 seconds (480184232 bytes allocated, 23.21% gc > time)
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
So the "call" syntax on a type works, but using the implementation referenced above, it is SLOW. # Slow, function callback function test1(f, n) summ=0 for i=1:n summ=summ+f(i) end return summ end g(i::Int)=i # Fast, hardwired function g() function test2(n) summ=0 for i=1:n summ=summ+g(i) end return summ end # Fast, using method defined for an object function test4{T}(o::T, n) summ=0 for i=1:n summ=summ+get(o,i) end return summ end type MyFun1 end function get(o::MyFun1,i::Int) return g(i) end # Slow, using "call" on a singleton type MyFun3 end call(::Type{MyFun3},i::Int)=g(i)::Int n=10002345; @time println("test1(g, n) = $( test1(g, n) )") @time println("test2(n) = $( test2(n) )") @time println("test4(MyFun1(), n) = $( test4(MyFun1(), n) )") @time println("test1(MyFun3, n) = $( test1(MyFun3, n) )") julia> include("fun.jl") test1(g, n) = 50023457750685 elapsed time: 0.610016329 seconds (480173520 bytes allocated, 27.80% gc time) test2(n) = 50023457750685 elapsed time: 0.003086749 seconds (75304 bytes allocated) test4(MyFun1(), n) = 50023457750685 elapsed time: 0.004098207 seconds (90436 bytes allocated) test1(MyFun3, n) = 50023457750685 elapsed time: 0.665630908 seconds (480184232 bytes allocated, 23.21% gc time)
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
Thank you all that responded re: the support for call methods in 0.4 . Petr On Thursday, January 15, 2015 at 7:28:06 AM UTC-8, Steven G. Johnson wrote: > > See also: > > > http://docs.julialang.org/en/latest/manual/methods/#call-overloading-and-function-like-objects > > On Thursday, January 15, 2015 at 4:29:57 AM UTC-5, Mauro wrote: >> >> > Is there an example of the use of this new syntax for 0.4? >> >> It's in the manual: >> http://docs.julialang.org/en/latest/stdlib/base/?highlight=call#Base.call >> >> http://docs.julialang.org/en/latest/manual/constructors/?highlight=call#constructors-call-and-conversion >> >> >> > Thanks, >> > >> > Petr >> > >> > On Sunday, January 11, 2015 at 12:20:39 PM UTC-8, Tobias Knopp wrote: >> >> >> >> The call syntax is part of 0.4 >> >> >> >> Cheers >> >> >> >> Tobi >> >> >> >> Am Sonntag, 11. Januar 2015 19:35:06 UTC+1 schrieb Petr Krysl: >> >>> >> >>> On Sunday, January 11, 2015 at 10:22:05 AM UTC-8, Tim Holy wrote: >> >> >> Already implement in julia 0.4. >> >> >>> >> >>> Very cool! Just checking: are you saying that the solution I >> proposed >> >>> with the empty types would actually address the problem of >> functions >> >>> being inefficient as when passed in as callbacks, and that this is >> now >> >>> part of 0.4? Or rather that the syntactic sugar of being able to call >> on >> >>> object is part of 0.4? >> >>> >> >>> Thanks, >> >>> >> >>> P >> >>> >> >> >> >>
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
See also: http://docs.julialang.org/en/latest/manual/methods/#call-overloading-and-function-like-objects On Thursday, January 15, 2015 at 4:29:57 AM UTC-5, Mauro wrote: > > > Is there an example of the use of this new syntax for 0.4? > > It's in the manual: > http://docs.julialang.org/en/latest/stdlib/base/?highlight=call#Base.call > > http://docs.julialang.org/en/latest/manual/constructors/?highlight=call#constructors-call-and-conversion > > > > Thanks, > > > > Petr > > > > On Sunday, January 11, 2015 at 12:20:39 PM UTC-8, Tobias Knopp wrote: > >> > >> The call syntax is part of 0.4 > >> > >> Cheers > >> > >> Tobi > >> > >> Am Sonntag, 11. Januar 2015 19:35:06 UTC+1 schrieb Petr Krysl: > >>> > >>> On Sunday, January 11, 2015 at 10:22:05 AM UTC-8, Tim Holy wrote: > > > Already implement in julia 0.4. > > >>> > >>> Very cool! Just checking: are you saying that the solution I > proposed > >>> with the empty types would actually address the problem of > functions > >>> being inefficient as when passed in as callbacks, and that this is > now > >>> part of 0.4? Or rather that the syntactic sugar of being able to call > on > >>> object is part of 0.4? > >>> > >>> Thanks, > >>> > >>> P > >>> > >> > >
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
> Is there an example of the use of this new syntax for 0.4? It's in the manual: http://docs.julialang.org/en/latest/stdlib/base/?highlight=call#Base.call http://docs.julialang.org/en/latest/manual/constructors/?highlight=call#constructors-call-and-conversion > Thanks, > > Petr > > On Sunday, January 11, 2015 at 12:20:39 PM UTC-8, Tobias Knopp wrote: >> >> The call syntax is part of 0.4 >> >> Cheers >> >> Tobi >> >> Am Sonntag, 11. Januar 2015 19:35:06 UTC+1 schrieb Petr Krysl: >>> >>> On Sunday, January 11, 2015 at 10:22:05 AM UTC-8, Tim Holy wrote: Already implement in julia 0.4. >>> >>> Very cool! Just checking: are you saying that the solution I proposed >>> with the empty types would actually address the problem of functions >>> being inefficient as when passed in as callbacks, and that this is now >>> part of 0.4? Or rather that the syntactic sugar of being able to call on >>> object is part of 0.4? >>> >>> Thanks, >>> >>> P >>> >>
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
*julia> **type GGG end* *julia> **call(::Type{GGG}, d::Int) = d* *call (generic function with 858 methods)* *julia> **GGG(4)* *4* *julia> **GGG(2)* *2* Cheers Tobias Am Mittwoch, 14. Januar 2015 23:09:26 UTC+1 schrieb Petr Krysl: > > Hi Tobias, > > Is there an example of the use of this new syntax for 0.4? > > Thanks, > > Petr > > On Sunday, January 11, 2015 at 12:20:39 PM UTC-8, Tobias Knopp wrote: >> >> The call syntax is part of 0.4 >> >> Cheers >> >> Tobi >> >> Am Sonntag, 11. Januar 2015 19:35:06 UTC+1 schrieb Petr Krysl: >>> >>> On Sunday, January 11, 2015 at 10:22:05 AM UTC-8, Tim Holy wrote: Already implement in julia 0.4. >>> >>> Very cool! Just checking: are you saying that the solution I proposed >>> with the empty types would actually address the problem of functions >>> being inefficient as when passed in as callbacks, and that this is now >>> part of 0.4? Or rather that the syntactic sugar of being able to call on >>> object is part of 0.4? >>> >>> Thanks, >>> >>> P >>> >>
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
Hi Tobias, Is there an example of the use of this new syntax for 0.4? Thanks, Petr On Sunday, January 11, 2015 at 12:20:39 PM UTC-8, Tobias Knopp wrote: > > The call syntax is part of 0.4 > > Cheers > > Tobi > > Am Sonntag, 11. Januar 2015 19:35:06 UTC+1 schrieb Petr Krysl: >> >> On Sunday, January 11, 2015 at 10:22:05 AM UTC-8, Tim Holy wrote: >>> >>> >>> Already implement in julia 0.4. >>> >> >> Very cool! Just checking: are you saying that the solution I proposed >> with the empty types would actually address the problem of functions >> being inefficient as when passed in as callbacks, and that this is now >> part of 0.4? Or rather that the syntactic sugar of being able to call on >> object is part of 0.4? >> >> Thanks, >> >> P >> >
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
Thanks everybody, we have to wait for the 0.4 release! when is this release foreseen?
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
The call syntax is part of 0.4 Cheers Tobi Am Sonntag, 11. Januar 2015 19:35:06 UTC+1 schrieb Petr Krysl: > > On Sunday, January 11, 2015 at 10:22:05 AM UTC-8, Tim Holy wrote: >> >> >> Already implement in julia 0.4. >> > > Very cool! Just checking: are you saying that the solution I proposed > with the empty types would actually address the problem of functions > being inefficient as when passed in as callbacks, and that this is now > part of 0.4? Or rather that the syntactic sugar of being able to call on > object is part of 0.4? > > Thanks, > > P >
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
On Sunday, January 11, 2015 at 10:22:05 AM UTC-8, Tim Holy wrote: > > > Already implement in julia 0.4. > Very cool! Just checking: are you saying that the solution I proposed with the empty types would actually address the problem of functions being inefficient as when passed in as callbacks, and that this is now part of 0.4? Or rather that the syntactic sugar of being able to call on object is part of 0.4? Thanks, P
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
On Sunday, January 11, 2015 09:46:51 AM Petr Krysl wrote: > The last solution on the list could be much improved syntactically if one > could define a "call" syntax for an object. Very recent post addresses > this need: > https://groups.google.com/forum/?fromgroups=#!topic/julia-users/blreJXpp-FQ Already implement in julia 0.4. --Tim
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
Here is a kludgy sort of solution. Tim and the other wizards will probably know if it was suggested before. https://gist.github.com/PetrKryslUCSD/7b96cd937e2e6cdb58db Measurements: elapsed time: 0.440441867 seconds (320050384 bytes allocated, 31.29% gc time) elapsed time: 0.001976364 seconds (62724 bytes allocated) elapsed time: 1.001955839 seconds (320046408 bytes allocated, 13.32% gc time) elapsed time: 0.002634663 seconds (76500 bytes allocated) elapsed time: 0.002585548 seconds (81116 bytes allocated) The last solution on the list could be much improved syntactically if one could define a "call" syntax for an object. Very recent post addresses this need: https://groups.google.com/forum/?fromgroups=#!topic/julia-users/blreJXpp-FQ Petr
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
I should probably be mentioned in http://docs.julialang.org/en/latest/manual/performance-tips/. It's also the reason for: f(i) = i @time map(f, rand(1)) @time [f(i) for i in rand(1)] where map is very slow compared to the array comprehension.
Re: [julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
If you search the dev & user archives, you'll see this issue has been reported many times, which is probably why you didn't get a rapid response to your initial question. Unfortunately it's not an easy fix. Other workarounds include "types as tags" (search; NumericFuns.jl is one example among many), FastAnonymous.jl, and in julia 0.4 the new call() overloading. --Tim On Sunday, January 11, 2015 02:56:16 AM Daniel Høegh wrote: > I have cooked up a minimum test case of you code that displays the problem. > If you have the following > > function test1(f, n) > for i=1:n > f(i) > end > end > function test2(n) > for i=1:n > g(i) > end > end > function test3(f, n) > for i=1:n > invoke(f, (Int,), i) > end > end > g(i) = i > > test1(g,10) > @time test1(g,10_000_000) > test2(10) > @time test2(10_000_000) > test3(g,10) > @time test3(g,10_000_000) > The output will be: > elapsed time: 0.38846745 seconds (320032108 bytes allocated, 35.61% gc time) > elapsed time: 1.259e-6 seconds (80 bytes allocated) > elapsed time: 0.814524146 seconds (319983728 bytes allocated, 17.09% gc > time) > > I think it's because the compiler cannot inline the function call to g in > the loop of test1, due to at next run of test1 f can have changed. this > causes it to do a function lookup at each loop step. I think this > https://github.com/JuliaLang/julia/pull/9642 will enhance this property at > least for test3.
[julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
I have cooked up a minimum test case of you code that displays the problem. If you have the following function test1(f, n) for i=1:n f(i) end end function test2(n) for i=1:n g(i) end end function test3(f, n) for i=1:n invoke(f, (Int,), i) end end g(i) = i test1(g,10) @time test1(g,10_000_000) test2(10) @time test2(10_000_000) test3(g,10) @time test3(g,10_000_000) The output will be: elapsed time: 0.38846745 seconds (320032108 bytes allocated, 35.61% gc time) elapsed time: 1.259e-6 seconds (80 bytes allocated) elapsed time: 0.814524146 seconds (319983728 bytes allocated, 17.09% gc time) I think it's because the compiler cannot inline the function call to g in the loop of test1, due to at next run of test1 f can have changed. this causes it to do a function lookup at each loop step. I think this https://github.com/JuliaLang/julia/pull/9642 will enhance this property at least for test3.
[julia-users] Speed of Julia when a function is passed as an argument, and a different, but much faster coding.
Dear all, I was comparing the speed of Julia versus other languages (like Python or Fortran). As a test case I decided to check the speed when a function is passed to another one (for an example in a Ode solver). This is just a test case for situations that can arise, I know that there are very good ode solvers in Julia. I have found that the following code is quite slow, as slow as Python. function eusolverfun(fun::Function, n::Int64, tend::Float64, x0::Float64, y0 ::Float64, a::Float64, b::Float64, c::Float64, d::Float64) x, y = x0, y0 dt = tend/n for i=1:n dx, dy = fun(x, y, a, b, c, d)::(Float64,Float64) x = x + dx*dt y = y + dy*dt end return x, y end function predpreyeq(x::Float64, y::Float64, a::Float64, b::Float64, c::Float64, d::Float64) dx = x*(a-b*y) dy = -y*(c-d*x) return dx, dy end function fullcalc(n) tend = 5.0 a, b, c, d = 1.5, 1.0, 3.0, 1.0 x0, y0 = 1.0, 1.0 x, y = eusolverfun(predpreyeq, 20, tend, x0, y0, a, b, c, d) @time x, y = eusolverfun(predpreyeq, n, tend, x0, y0, a, b, c, d) end fullcalc(int(1e7)) I much faster version, as fast as Fortran actually, is the following: module genode export Ode, eusolver abstract Ode function eusolver(ode::Ode, n, tend, x0, y0) x, y = x0, y0 dt = tend/n for i=1:n dx, dy = eqfun(ode, x, y) x = x + dx*dt y = y + dy*dt end return x, y end eqfun(ode::Ode, x, y) = (x,y) end using genode import genode.eqfun immutable MyOde <: Ode a::Float64 b::Float64 c::Float64 d::Float64 end function eqfun(ode::MyOde, x, y) dx = x*(ode.a-ode.b*y) dy = -y*(ode.c-ode.d*x) return dx, dy end n = int(1E9) w = MyOde(1.5, 1.0, 3.0, 1.0) x, y = eusolver(w, 10, 5.0, 1.0, 1.0) @time x, y = eusolver(w, n, 5.0, 1.0, 1.0) On my windows machine the first program for n=1e7 gives: elapsed time: 2.603235344 seconds (161792 bytes allocated, 40.55% gc time) While the second one gives (n=1e9): elapsed time: 6.615803974 seconds (208 bytes allocated) Is there a way to code first version in order to be as fast as the second? While the second version could be quite handy for passing parameters to the Ode, one still needs to declare a placeholder function (*eqfun(ode::Ode, ...)* in module genode) and import it in order to allow the overloading of the function to take place. Thanks.