Skip to content

Instantly share code, notes, and snippets.

@jwscook
Created June 9, 2018 13:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jwscook/e8440d7f76c92b4fb622b58b899f12c2 to your computer and use it in GitHub Desktop.
Save jwscook/e8440d7f76c92b4fb622b58b899f12c2 to your computer and use it in GitHub Desktop.
Avoiding functions in types; performance comparison & invitation for code review
module Functionals
abstract type Abstract end
type Functional <: Abstract
lower::Float64
upper::Float64
end
Functional(t::Float64) = Functional(0.0, 12.0 * t)
end
include("Functionals.jl")
include("Objects.jl")
include("Work.jl")
using BenchmarkTools
const t = Float64(π)
O = Objects.Object(t)
F = Functionals.Functional(t)
function (Functionals.Functional)(x::T, ::Type{Val{false}}) where {T}
return exp(-x.^2 / t^2)
end
function (Functionals.Functional)(x::T, ::Type{Val{true}}) where {T}
return -2 * x / t^2 * exp(-x.^2 / t^2)
end
#make sure they all do the same number crunching
@show Work.work(t, false), Work.work(O, false), Work.work(F, false)
@show Work.work(t, true), Work.work(O, true), Work.work(F, true)
# assert that they do...
@assert Work.work(O, false) == Work.work(F, false)
@assert Work.work(O, true) == Work.work(F, true)
@assert Work.work(O, true) == Work.work(t, true)
@assert Work.work(O, false) == Work.work(t, false)
# run a few times out of order in case of background cpu usage
@btime Work.work($t, false)
@btime Work.work($O, false)
@btime Work.work($F, false)
@btime Work.work($t, true)
@btime Work.work($O, true)
@btime Work.work($F, true)
@btime Work.work($t, false)
@btime Work.work($t, true)
@btime Work.work($O, false)
@btime Work.work($O, true)
@btime Work.work($F, false)
@btime Work.work($F, true)
# print warntype
@show "#########"
@show "code_warntype, Work.work(t, false)"
@code_warntype Work.work(t, false)
@show "#########"
@show "code_warntype, Work.work(O, false)"
@code_warntype Work.work(O, false)
@show "#########"
@show "code_warntype, Work.work(F, false)"
@code_warntype Work.work(F, false)
@show "#########"
# look at native code
@show "#########"
@show "code_native, Work.work(t, false)"
@code_native Work.work(t, false)
@show "#########"
@show "code_native, Work.work(O, false)"
@code_native Work.work(O, false)
@show "#########"
@show "code_native, Work.work(F, false)"
@code_native Work.work(F, false)
module Objects
abstract type Abstract end
type Object{T<:Function, U<:Function} <: Abstract
F::T
dFdv::U
lower::Float64
upper::Float64
end
defaultF(t::T) where{T} = x::T -> exp(-x^2 / t^2)
defaultdFdv(t::T) where{T} = x::T -> - 2 * x / t^2 * exp(-x^2 / t^2)
Object(t::T) where {T} = Object(defaultF(t), defaultdFdv(t), 0.0, 12.0 * t)
end # module
module Work
using QuadGK, SpecialFunctions
import Objects, Functionals
kernel(x::T) where {T<:Number} = (x^3)::T *besselj(3, x)::T * besselj(-2, x)::T
function work(obj::T, ∂::Bool) where {T<:Objects.Abstract}
integrand(x::U) where {U<:Number} = ∂ ? kernel(x)*obj.dFdv(x) : kernel(x)*obj.F(x)
return QuadGK.quadgk(integrand, obj.lower, obj.upper)[1]
end
function work(fun::T, ∂::Bool) where {T<:Functionals.Abstract}
integrand(x::U) where {U<:Number} = kernel(x) * T(x, Val{∂})
return QuadGK.quadgk(integrand, fun.lower, fun.upper)[1]
end
function work(t::Float64, ∂::Bool)
integrand(x::T) where {T<:Number} = ∂ ?
kernel(x)*(- 2 * x / t^2 * exp(-x^2 / t^2)) : kernel(x)*exp(-x^2/t^2)
return QuadGK.quadgk(integrand, 0.0, 12.0 * t)[1]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment