Skip to content

Instantly share code, notes, and snippets.

@timholy
Last active August 29, 2015 14:01
Show Gist options
  • Save timholy/bdcee95f9b7725214d8b to your computer and use it in GitHub Desktop.
Save timholy/bdcee95f9b7725214d8b to your computer and use it in GitHub Desktop.
Function inlining demonstration
# We're going to create a function, sumf(func, x), that computes
# sum(func(x)) with func applied to each element of the array x.
# The cool part is that we won't create a temporary array y = func(x),
# as we would if we relied on func being vectorized.
# Here's a function we'll use for our testing
sinc_plus_x(x) = sin(x)/x + x
# For comparison, here's the hand-written version of sumf(sinc_plus_x, x)
function sum_sinc_plus_x(x::AbstractArray)
s = 0.0
for xs in x
s += sinc_plus_x(xs)
end
s
end
# Here's the general version. It generates a separate function
# for each supplied user function, and stores each generated function
# for future use.
global sumf
let _sumf_method_cache = Dict() # keep this private
function sumf(func::Function, x::AbstractArray)
if !haskey(_sumf_method_cache, func)
# If we haven't generated the function yet, do so now and store the result
F = Expr(:quote, func)
f = eval(quote
local _sumf_ # to keep this from being defined externally
function _sumf_(x::AbstractArray)
s = 0.0
for xs in x
s += ($F)(xs)
end
s
end
end)
_sumf_method_cache[func] = f
else
# Use the previously-defined version
f = _sumf_method_cache[func]
end
f(x) # Evaluate the function on our arguments
end
end # end of let
x = rand(10^7)
println("Testing the hand-written version")
@time sum_sinc_plus_x(x)
gc() # so garbage-collection doesn't influence the results
@time vmanual = sum_sinc_plus_x(x)
println("Testing the generated version")
@time sumf(sinc_plus_x, x)
gc()
@time vgen = sumf(sinc_plus_x, x)
@assert vmanual == vgen
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment