Re: [julia-users] convincing Julia that a function call (via a variable) has a stable return type

2015-01-21 Thread Keith Mason
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

2015-01-20 Thread Mauro
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

2015-01-20 Thread Erik Schnetter
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

2015-01-20 Thread Jeff Bezanson
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

2015-01-20 Thread Jeff Bezanson
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

2015-01-20 Thread Keith Mason
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

2015-01-20 Thread Jeff Bezanson
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

2015-01-20 Thread Keith Mason
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

2015-01-20 Thread Keith Mason
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.