Re: [julia-users] Re: passing function as arguments and avoiding unecessary allocations

2015-12-28 Thread Ismael VC
How about this?

julia> sinc{T<:AbstractFloat}(x::T) = x != 0 ? sin(π*x)/(π*x) : one(T)
sinc (generic function with 1 method)

julia> methods(sinc)
# 1 method for generic function "sinc":
sinc{T<:AbstractFloat}(x::T<:AbstractFloat) at none:1

julia> @vectorize_1arg AbstractFloat sinc
sinc (generic function with 4 methods)

julia> methods(sinc)
# 4 methods for generic function "sinc":
sinc{T<:AbstractFloat}(x::T<:AbstractFloat) at none:1
sinc{T<:AbstractFloat}(::AbstractArray{T<:AbstractFloat,1}) at operators.jl:380
sinc{T<:AbstractFloat}(::AbstractArray{T<:AbstractFloat,2}) at operators.jl:381
sinc{T<:AbstractFloat}(::AbstractArray{T<:AbstractFloat,N}) at operators.jl:383

julia> @time sinc(rand(10_000));
  0.055184 seconds (45.92 k allocations: 2.139 MB)

julia> @time sinc(rand(10_000));
  0.000251 seconds (10 allocations: 156.563 KB)

julia> @code_warntype sinc(rand(10_000))
Variables:
  #102#x::Array{Float64,1}
  #s76::Int64
  #s75::Int64
  #s74::Int64
  #101#i::Int64
  #s73::Int64

Body:
  begin  # operators.jl, line 380:
  GenSym(8) = (Base.arraylen)(#102#x::Array{Float64,1})::Int64
  GenSym(0) = $(Expr(:new, UnitRange{Int64}, 1, :(((top(getfield))(Base.Intr
insics,:select_value)::I)((Base.sle_int)(1,GenSym(8))::Bool,GenSym(8),(Base.box)
(Int64,(Base.sub_int)(1,1)))::Int64)))
  GenSym(1) = (Base.box)(Int64,(Base.checked_sadd)((Base.box)(Int64,(Base.ch
ecked_ssub)((top(getfield))(GenSym(0),:stop)::Int64,(top(getfield))(GenSym(0),:s
tart)::Int64)),1))
  0:
  GenSym(3) = (top(ccall))(:jl_alloc_array_1d,(top(apply_type))(Base.Array,F
loat64,1)::Type{Array{Float64,1}},(top(svec))(Base.Any,Base.Int)::SimpleVector,A
rray{Float64,1},0,GenSym(1),0)::Array{Float64,1}
  #s76 = 1
  #s75 = (top(getfield))(GenSym(0),:start)::Int64
  #s74 = 0
  unless (Base.box)(Base.Bool,(Base.not_int)(#s74::Int64 === GenSym(1)::Bool
)) goto 2
  3:
  #s74 = (Base.box)(Base.Int,(Base.add_int)(#s74::Int64,1))
  GenSym(10) = #s75::Int64
  GenSym(11) = (Base.box)(Base.Int,(Base.add_int)(#s75::Int64,1))
  #s73 = 1
  GenSym(12) = GenSym(10)
  GenSym(13) = (Base.box)(Base.Int,(Base.add_int)(1,1))
  #101#i = GenSym(12)
  #s73 = GenSym(13)
  GenSym(14) = GenSym(11)
  GenSym(15) = (Base.box)(Base.Int,(Base.add_int)(2,1))
  #s75 = GenSym(14)
  #s73 = GenSym(15)
  GenSym(4) = (Main.sinc)((Base.arrayref)(#102#x::Array{Float64,1},#101#i::I
nt64)::Float64)::Float64
  $(Expr(:type_goto, 0, GenSym(4)))
  $(Expr(:boundscheck, false))
  (Base.arrayset)(GenSym(3),GenSym(4),#s76::Int64)::Array{Float64,1}
  $(Expr(:boundscheck, :(Main.pop)))
  #s76 = (Base.box)(Base.Int,(Base.add_int)(#s76::Int64,1))
  4:
  unless (Base.box)(Base.Bool,(Base.not_int)((Base.box)(Base.Bool,(Base.not_
int)(#s74::Int64 === GenSym(1)::Bool goto 3
  2:
  1:
  return GenSym(3)
  end::Array{Float64,1}

julia> sinc(rand(4, 4))
4x4 Array{Float64,2}:
 0.671308  0.28010.110566  0.0508818
 0.201512  0.416824  0.993366  0.537811
 0.999858  0.74607   0.836841  0.0222563
 0.592876  0.667453  0.612684  0.81811

julia> sinc(rand(4, 4, 2))
4x4x2 Array{Float64,3}:
[:, :, 1] =
 0.1301 0.406598  0.95419   0.0530077
 0.810275   0.917711  0.94  0.289211
 0.0391342  0.970136  0.456169  0.34722
 0.565740.726088  0.956873  0.99049

[:, :, 2] =
 0.632377  0.844147  0.963265  0.0472808
 0.569625  0.834078  0.183842  0.323166
 0.51727   0.989112  0.568156  0.874306
 0.533161  0.988943  0.931382  0.133851

julia>

​

Ismael Venegas Castelló

*Data Analyst*

Cel. 044 55 6434 0229

ivene...@richit.com.mx

Cerro San Francisco 357, C.P. 04200

Campestre Churubusco, Coyoacán

Ciudad de México




  

Tel. 6718 1818
richit.com.mx

2015-12-27 15:00 GMT-06:00 alan souza :

> Thanks for the tip. I was trying to annotate the function call before the
> loop without success.
>
> Do you know the reason for the speedup? Because the extra allocations
> still happening albeit a little less.
>
> thanks
>
> On Sunday, December 27, 2015 at 5:07:56 PM UTC-2, Lutfullah Tomak wrote:
>>
>> It seems adding typecheck is 2x improvements in my laptop.
>>y = zeros(T, n)
>> for i in eachindex(X)
>> y[i] = F(X[i])::T
>> end
>> return y
>>
>


[julia-users] Re: passing function as arguments and avoiding unecessary allocations

2015-12-28 Thread alan souza
Thanks for the tip. I was trying to annotate the function call before the 
loop without success.

Do you know the reason for the speedup? Because the extra allocations still 
happening albeit a little less.

thanks

On Sunday, December 27, 2015 at 5:07:56 PM UTC-2, Lutfullah Tomak wrote:
>
> It seems adding typecheck is 2x improvements in my laptop.
>y = zeros(T, n)
> for i in eachindex(X)
> y[i] = F(X[i])::T
> end
> return y
>


[julia-users] Re: passing function as arguments and avoiding unecessary allocations

2015-12-27 Thread Ismael Venegas Castelló
Alan please don't double post the same 
question: https://groups.google.com/forum/#!topic/julia-users/2AoQQKVP2Do

It makes it difficult to follow the thread, thanks!

El domingo, 27 de diciembre de 2015, 11:21:35 (UTC-6), alan souza escribió:
>
> Hi. I was wondering what is the correct way to pass a function as argument 
> preserving the return type information
>
> For instance in the following code:
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> *function sinc{T<:Real}(x::T)return T((x != zero(T) 
> )?(sin(pi*x)/(pi*x)):(one(T)))endfunction calcF{T<:Real}(X::Array{T,1}, 
> F::Function)n = length(X); @assert(n > 0)y = zeros(T, n)for 
> i in eachindex(X)y[i] = F(X[i])endreturn yendfunction 
> calcSinc{T<:Real}(X::Array{T,1})n = length(X); @assert(n > 0)y 
> = zeros(T, n)for i in eachindex(X)y[i] = sinc(X[i])end
> return yendfunction main{T<:Real}(min::T, max::T, d::T)X = 
> collect(min:d:max)calcF(X, sinc)calcSinc(X)@code_warntype 
> calcF(X, sinc)@time calcF(X, sinc)@code_warntype calcSinc(X)
> @time calcSinc(X)YF = calcF(X, sinc)YS = 
> calcSinc(X)endmain(-1.0*pi,1.0*pi,0.1)*After running this code I got 
> these results (using @code_warntype and @time) :
> function CalcF:
>
>
>
>
>
>
> *  #s1 = GenSym(5) # /home/user/scratch/julia/test.jl, line 10:  
> GenSym(2) = 
> (F::F)((Base.arrayref)(X::Array{Float64,1},i::Int64)::Float64)::ANY  
> (Base.arrayset)(y::Array{Float64,1},(top(typeassert))((Base.convert)(Float64,GenSym(2))::ANY,Float64)::Float64,i::Int64)::Array{Float64,1}
>   
> 5:   unless 
> (Base.box)(Base.Bool,(Base.not_int)((Base.box)(Base.Bool,(Base.not_int)(#s1::Int64
>  
> === 
> (Base.box)(Base.Int,(Base.add_int)((top(getfield))(GenSym(0),:stop)::Int64,1))::Bool
>  
> goto 4  3:   0.080181 seconds (1.88 M allocations: 33.556 MB, 6.41% gc 
> time)*
>
> but for the function calcSinc:
>
>
>
>
>
>
> *  #s1 = GenSym(5) # /home/user/scratch/julia/test.jl, line 20:  
> GenSym(2) = 
> (Main.sinc)((Base.arrayref)(X::Array{Float64,1},i::Int64)::Float64)::Float64  
> 
> (Base.arrayset)(y::Array{Float64,1},GenSym(2),i::Int64)::Array{Float64,1} 
>  
> 5:   unless 
> (Base.box)(Base.Bool,(Base.not_int)((Base.box)(Base.Bool,(Base.not_int)(#s1::Int64
>  
> === 
> (Base.box)(Base.Int,(Base.add_int)((top(getfield))(GenSym(0),:stop)::Int64,1))::Bool
>  
> goto 4  3:   0.031224 seconds (2 allocations: 4.794 MB)*
>
> Is there a way to avoid these allocation on the first case?
>
> thanks.
>