Last active
August 29, 2015 14:01
-
-
Save timholy/bdcee95f9b7725214d8b to your computer and use it in GitHub Desktop.
Function inlining demonstration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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