Function with initialized data


#1

Hi all,

I have a function using data which has to be initialized at run-time. Here is a basic example:

type Test{T<:Number}
       x::T
       a::Array{T, 1}
end

function f(t::Test, x)
       i = floor(Integer, x - t.x)
       return x*t.a[i]
end

(t::Test)(x) = f(t, x) #functor definition

t = Test(3., rand(100)); #initialize data

if I map this function on an array, I get quite different performance whether I use the function f or the functor-call:

#init
rsi	= rand(10)*100 + 4;
@timed map(x -> f(t, x), rsi);
map(t, rsi);			

#test	
rs	= rand(10^7)*100 + 4;	
@time map(x -> f(t, x), rs);  
#1.349930 seconds (20.03 M allocations: 382.873 MB, 26.17% gc time)

@time map(t, rs);
#  0.290798 seconds (7 allocations: 76.294 MB, 0.83% gc time)

The difference is even bigger when I use vectorized functions:

#init
ft(x) = f(t, x)
ft.(rsi);
t.(rsi);
#test
@time ft.(rs);
#2.698942 seconds (30.00 M allocations: 534.059 MB, 8.62% gc time)
@time t.(rs);
#0.305188 seconds (7 allocations: 76.294 MB, 1.57% gc time)

So far so good, if I want to map the function I simply have to use the functor. However, what am I going to do if I have additional functions which need the same initialized data? I could of course define a type for each function, but that does not seem very elegant.

Any suggestions? Am I missing something?


#2

Don’t benchmark in global scope: put the variable definitions and the benchmarking code inside a function.


#3

As simple as that :slight_smile:

Thanks a lot!


#4

Alternatively (and preferably), use the BenchmarkTooks.jl package.