Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type
I figured out my problem. I was pre-creating and storing CFunction{Float64,Float64} objects in an Array{CFunction,1}. This was causing f to be a CFunction rather than a CFunction{Float64,Float64}. So the Julia compiler was a bit confused as to what my return type was going to be. I've got it worked out, and it does work. Thanks! On Tuesday, January 20, 2015 at 10:19:51 PM UTC-6, Jeff Bezanson wrote: That's surprising; I get the same speedup in 0.3 with function test2() f = CFunction{Float64,Float64}(foo) for i=1:1 r = call(f, 1.0) goo(r) end end -- Please click here http://www.e-disclaimer.com/conning/AD21D06B4CC99D2B4F24BA73FB4EED83.htm for important information regarding this e-mail communication.
Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type
Have a look at https://groups.google.com/d/msg/julia-dev/JEiH96ofclY/_amm9Cah6YAJ there are some hack-y solutions mentioned there. If I recall correctly, using a constructor instead of a function can solve the problem. On Tue, 2015-01-20 at 22:16, Keith Mason keith.ma...@conning.com wrote: I am trying to make use of functions as data, where I store functions in an array and call them in a loop. All of my functions return Float64, but because I am assigning the function to a variable before calling it, Julia can't figure that out. Here's some example code: foo() = 0.0 goo(x::Float64) = x So if I am to call goo(foo()), this is quite type stable and results in virtually no code. If I call it in a loop 100,000,000 times, it takes about a millisecond. However, if I do this: function test1() for i=1:1 f = foo r = f() goo(r) end end Now I'm in trouble. Even though Julia knows that foo returns a float, it doesn't know that f returns a float. This code in a loop of 100,000,000 takes nearly 8 seconds and allocates 32GB of RAM. (Honestly, this strikes me as an optimization that just doesn't yet exist, but my use case is a little more complicated; in my case, f can be one of multiple functions, selected by a parameter. But let's set that aside for the purposes of this question.) Declaring the type of the variable doesn't help; in fact, it makes it worse: function test2() for i=1:1 f = foo r::Float64 = f() goo(r) end end But I can improve the situation a bit by casting the result of the function. function test3() for i=1:1 f = foo r = f()::Float64 goo(r) end end This cuts run time and memory allocation in half. But it is still taking too long because it has to check if f returns a float before assigning it to t. @code_lowered shows that a call to typeassert is the culprit here. Is there any way I can promise Julia that f returns float so it doesn't have to call typeassert? I tried f::Function{Float64} = foo and f::Function::Float64 but I can't find any syntax that works. I know there is a macro @inbounds https://github.com/inbounds to turn off bounds checking; is there something similar that turns off type checking?
Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type
I the `cfunction` necessary here? Since you already have the return type `R`, wouldn't it suffice to annotate the call with a `::R` suffix? I am thinking: immutable StableFunction{R,A} f StableFunction(f) = new(f) end call{R,A}(f::StableFunction{R,A}, x) = f(x)::R -erik On Jan 20, 2015, at 17:56 , Jeff Bezanson jeff.bezan...@gmail.com wrote: Oh, I should also mention that the version that calls goo(foo()) takes so little time because the entire loop is probably optimized out. On Tue, Jan 20, 2015 at 5:54 PM, Jeff Bezanson jeff.bezan...@gmail.com wrote: Here is a hack that basically works by escaping through the C type system: ``` immutable CFunction{R,A} f p::Ptr{Void} CFunction(f) = new(f, cfunction(f, R, (A,))) end call{R,A}(f::CFunction{R,A}, x) = ccall(f.p, R, (A,), x) foo(x::Float64) = 0.0 goo(x::Float64) = x function test1() for i=1:1 f = foo r = f(1.0) goo(r) end end function test2() f = CFunction{Float64,Float64}(foo) for i=1:1 r = f(1.0) goo(r) end end ``` I added an argument to `foo` to increase the generality somewhat. test1() is the original test case. test2() is the new version. The CFunction object needs to be constructed outside the loop, but this can be stored in a data structure and reused anywhere. -Jeff On Tue, Jan 20, 2015 at 4:34 PM, Ivar Nesje iva...@gmail.com wrote: Originally posted at https://github.com/JuliaLang/julia/issues/9863 -- Erik Schnetter schnet...@gmail.com http://www.perimeterinstitute.ca/personal/eschnetter/ My email is as private as my paper mail. I therefore support encrypting and signing email messages. Get my PGP key from https://sks-keyservers.net. signature.asc Description: Message signed with OpenPGP using GPGMail
Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type
Oh, I should also mention that the version that calls goo(foo()) takes so little time because the entire loop is probably optimized out. On Tue, Jan 20, 2015 at 5:54 PM, Jeff Bezanson jeff.bezan...@gmail.com wrote: Here is a hack that basically works by escaping through the C type system: ``` immutable CFunction{R,A} f p::Ptr{Void} CFunction(f) = new(f, cfunction(f, R, (A,))) end call{R,A}(f::CFunction{R,A}, x) = ccall(f.p, R, (A,), x) foo(x::Float64) = 0.0 goo(x::Float64) = x function test1() for i=1:1 f = foo r = f(1.0) goo(r) end end function test2() f = CFunction{Float64,Float64}(foo) for i=1:1 r = f(1.0) goo(r) end end ``` I added an argument to `foo` to increase the generality somewhat. test1() is the original test case. test2() is the new version. The CFunction object needs to be constructed outside the loop, but this can be stored in a data structure and reused anywhere. -Jeff On Tue, Jan 20, 2015 at 4:34 PM, Ivar Nesje iva...@gmail.com wrote: Originally posted at https://github.com/JuliaLang/julia/issues/9863
Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type
That's surprising; I get the same speedup in 0.3 with function test2() f = CFunction{Float64,Float64}(foo) for i=1:1 r = call(f, 1.0) goo(r) end end
Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type
When I try this, I get an error: ERROR: type: test2: in apply, expected Function, got CFunction{Float64,Float64} It looks like call doesn't exist in version 0.3. I suppose I need 0.4 to make this work. It doesn't appear from the docs that call used to be named something else. On Tuesday, January 20, 2015 at 4:54:08 PM UTC-6, Jeff Bezanson wrote: Here is a hack that basically works by escaping through the C type system: ``` immutable CFunction{R,A} f p::Ptr{Void} CFunction(f) = new(f, cfunction(f, R, (A,))) end call{R,A}(f::CFunction{R,A}, x) = ccall(f.p, R, (A,), x) foo(x::Float64) = 0.0 goo(x::Float64) = x function test1() for i=1:1 f = foo r = f(1.0) goo(r) end end function test2() f = CFunction{Float64,Float64}(foo) for i=1:1 r = f(1.0) goo(r) end end ``` I added an argument to `foo` to increase the generality somewhat. test1() is the original test case. test2() is the new version. The CFunction object needs to be constructed outside the loop, but this can be stored in a data structure and reused anywhere. -Jeff On Tue, Jan 20, 2015 at 4:34 PM, Ivar Nesje iva...@gmail.com javascript: wrote: Originally posted at https://github.com/JuliaLang/julia/issues/9863 -- Please click here http://www.e-disclaimer.com/conning/AD21D06B4CC99D2B4F24BA73FB4EED83.htm for important information regarding this e-mail communication.
Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type
Here is a hack that basically works by escaping through the C type system: ``` immutable CFunction{R,A} f p::Ptr{Void} CFunction(f) = new(f, cfunction(f, R, (A,))) end call{R,A}(f::CFunction{R,A}, x) = ccall(f.p, R, (A,), x) foo(x::Float64) = 0.0 goo(x::Float64) = x function test1() for i=1:1 f = foo r = f(1.0) goo(r) end end function test2() f = CFunction{Float64,Float64}(foo) for i=1:1 r = f(1.0) goo(r) end end ``` I added an argument to `foo` to increase the generality somewhat. test1() is the original test case. test2() is the new version. The CFunction object needs to be constructed outside the loop, but this can be stored in a data structure and reused anywhere. -Jeff On Tue, Jan 20, 2015 at 4:34 PM, Ivar Nesje iva...@gmail.com wrote: Originally posted at https://github.com/JuliaLang/julia/issues/9863
Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type
It is, but I created a form that forces it to not be inlined, and that still runs in just 30 ms. On Tuesday, January 20, 2015 at 4:57:00 PM UTC-6, Jeff Bezanson wrote: Oh, I should also mention that the version that calls goo(foo()) takes so little time because the entire loop is probably optimized out. On Tue, Jan 20, 2015 at 5:54 PM, Jeff Bezanson jeff.b...@gmail.com javascript: wrote: Here is a hack that basically works by escaping through the C type system: ``` immutable CFunction{R,A} f p::Ptr{Void} CFunction(f) = new(f, cfunction(f, R, (A,))) end call{R,A}(f::CFunction{R,A}, x) = ccall(f.p, R, (A,), x) foo(x::Float64) = 0.0 goo(x::Float64) = x function test1() for i=1:1 f = foo r = f(1.0) goo(r) end end function test2() f = CFunction{Float64,Float64}(foo) for i=1:1 r = f(1.0) goo(r) end end ``` I added an argument to `foo` to increase the generality somewhat. test1() is the original test case. test2() is the new version. The CFunction object needs to be constructed outside the loop, but this can be stored in a data structure and reused anywhere. -Jeff On Tue, Jan 20, 2015 at 4:34 PM, Ivar Nesje iva...@gmail.com javascript: wrote: Originally posted at https://github.com/JuliaLang/julia/issues/9863 -- Please click here http://www.e-disclaimer.com/conning/AD21D06B4CC99D2B4F24BA73FB4EED83.htm for important information regarding this e-mail communication.
Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type
I tried that, but it was slower than my initial method of calling f(). I even tried called ccall directly, but it also didn't solve the problem of type instability (which makes me feel like I'm missing something important), and it had an additional problem of not accepting its type arguments as variables. I'm going to try 0.4 tomorrow and see how it goes. On Tuesday, January 20, 2015 at 10:06:40 PM UTC-6, Jeff Bezanson wrote: Oops, that's right, `call` only exists in 0.4. Probably the quickest way to make this work in 0.3 is to write `call(f, x)` instead of `f(x)` where needed. On Tue, Jan 20, 2015 at 10:14 PM, Keith Mason keith...@conning.com javascript: wrote: When I try this, I get an error: ERROR: type: test2: in apply, expected Function, got CFunction{Float64,Float64} It looks like call doesn't exist in version 0.3. I suppose I need 0.4 to make this work. It doesn't appear from the docs that call used to be named something else. On Tuesday, January 20, 2015 at 4:54:08 PM UTC-6, Jeff Bezanson wrote: Here is a hack that basically works by escaping through the C type system: ``` immutable CFunction{R,A} f p::Ptr{Void} CFunction(f) = new(f, cfunction(f, R, (A,))) end call{R,A}(f::CFunction{R,A}, x) = ccall(f.p, R, (A,), x) foo(x::Float64) = 0.0 goo(x::Float64) = x function test1() for i=1:1 f = foo r = f(1.0) goo(r) end end function test2() f = CFunction{Float64,Float64}(foo) for i=1:1 r = f(1.0) goo(r) end end ``` I added an argument to `foo` to increase the generality somewhat. test1() is the original test case. test2() is the new version. The CFunction object needs to be constructed outside the loop, but this can be stored in a data structure and reused anywhere. -Jeff On Tue, Jan 20, 2015 at 4:34 PM, Ivar Nesje iva...@gmail.com wrote: Originally posted at https://github.com/JuliaLang/julia/issues/9863 Please click here for important information regarding this e-mail communication. -- Please click here http://www.e-disclaimer.com/conning/AD21D06B4CC99D2B4F24BA73FB4EED83.htm for important information regarding this e-mail communication.