Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
jrevels committed Mar 7, 2017
1 parent 8e26415 commit e54c6cd
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 120 deletions.
50 changes: 25 additions & 25 deletions src/api/Config.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# AbstractConfig #
##################

abstract AbstractConfig
@compat abstract type AbstractConfig end

Base.show(io::IO, cfg::AbstractConfig) = print(io, typeof(cfg).name)

Expand All @@ -12,16 +12,16 @@ Base.show(io::IO, cfg::AbstractConfig) = print(io, typeof(cfg).name)

immutable GradientConfig{I} <: AbstractConfig
input::I
tape::RawTape
tape::InstructionTape
# disable default outer constructor
GradientConfig(input, tape) = new(input, tape)
end

# "private" convienence constructor
_GradientConfig{I}(input::I, tape::RawTape) = GradientConfig{I}(input, tape)
_GradientConfig{I}(input::I, tape::InstructionTape) = GradientConfig{I}(input, tape)

"""
ReverseDiff.GradientConfig(input, tp::RawTape = RawTape())
ReverseDiff.GradientConfig(input, tp::InstructionTape = InstructionTape())
Return a `GradientConfig` instance containing the preallocated tape and work buffers used
by the `ReverseDiff.gradient`/`ReverseDiff.gradient!` methods.
Expand All @@ -32,21 +32,21 @@ the target function's output.
See `ReverseDiff.gradient` for a description of acceptable types for `input`.
"""
GradientConfig{T}(input::AbstractArray{T}, tp::RawTape = RawTape()) = GradientConfig(input, T, tp)
GradientConfig{T}(input::AbstractArray{T}, tp::InstructionTape = InstructionTape()) = GradientConfig(input, T, tp)

GradientConfig(input::Tuple, tp::RawTape = RawTape()) = GradientConfig(input, eltype(first(input)), tp)
GradientConfig(input::Tuple, tp::InstructionTape = InstructionTape()) = GradientConfig(input, eltype(first(input)), tp)

"""
ReverseDiff.GradientConfig(input, ::Type{D}, tp::RawTape = RawTape())
ReverseDiff.GradientConfig(input, ::Type{D}, tp::InstructionTape = InstructionTape())
Like `GradientConfig(input, tp)`, except the provided type `D` is assumed to be the element
type of the target function's output.
"""
function GradientConfig{D}(input::Tuple, ::Type{D}, tp::RawTape = RawTape())
function GradientConfig{D}(input::Tuple, ::Type{D}, tp::InstructionTape = InstructionTape())
return _GradientConfig(map(x -> track(similar(x), D, tp), input), tp)
end

function GradientConfig{D}(input::AbstractArray, ::Type{D}, tp::RawTape = RawTape())
function GradientConfig{D}(input::AbstractArray, ::Type{D}, tp::InstructionTape = InstructionTape())
return _GradientConfig(track(similar(input), D, tp), tp)
end

Expand All @@ -57,16 +57,16 @@ end
immutable JacobianConfig{I,O} <: AbstractConfig
input::I
output::O
tape::RawTape
tape::InstructionTape
# disable default outer constructor
JacobianConfig(input, output, tape) = new(input, output, tape)
end

# "private" convienence constructor
_JacobianConfig{I,O}(input::I, output::O, tape::RawTape) = JacobianConfig{I,O}(input, output, tape)
_JacobianConfig{I,O}(input::I, output::O, tape::InstructionTape) = JacobianConfig{I,O}(input, output, tape)

"""
ReverseDiff.JacobianConfig(input, tp::RawTape = RawTape())
ReverseDiff.JacobianConfig(input, tp::InstructionTape = InstructionTape())
Return a `JacobianConfig` instance containing the preallocated tape and work buffers used
by the `ReverseDiff.jacobian`/`ReverseDiff.jacobian!` methods.
Expand All @@ -77,7 +77,7 @@ the target function's output.
See `ReverseDiff.jacobian` for a description of acceptable types for `input`.
ReverseDiff.JacobianConfig(input, ::Type{D}, tp::RawTape = RawTape())
ReverseDiff.JacobianConfig(input, ::Type{D}, tp::InstructionTape = InstructionTape())
Like `JacobianConfig(input, tp)`, except the provided type `D` is assumed to be the element
type of the target function's output.
Expand All @@ -88,7 +88,7 @@ function JacobianConfig(args...)
end

"""
ReverseDiff.JacobianConfig(output::AbstractArray, input, tp::RawTape = RawTape())
ReverseDiff.JacobianConfig(output::AbstractArray, input, tp::InstructionTape = InstructionTape())
Return a `JacobianConfig` instance containing the preallocated tape and work buffers used
by the `ReverseDiff.jacobian`/`ReverseDiff.jacobian!` methods. This method assumes the
Expand All @@ -99,25 +99,25 @@ stored or modified in any way.
See `ReverseDiff.jacobian` for a description of acceptable types for `input`.
"""
function JacobianConfig{D}(output::AbstractArray{D}, input::Tuple, tp::RawTape = RawTape())
function JacobianConfig{D}(output::AbstractArray{D}, input::Tuple, tp::InstructionTape = InstructionTape())
cfg_input = map(x -> track(similar(x), D, tp), input)
cfg_output = track!(similar(output, TrackedReal{D,D,Void}), output, tp)
return _JacobianConfig(cfg_input, cfg_output, tp)
end

# we dispatch on V<:Real here because RawTape is actually also an AbstractArray
function JacobianConfig{D,V<:Real}(output::AbstractArray{D}, input::AbstractArray{V}, tp::RawTape = RawTape())
# we dispatch on V<:Real here because InstructionTape is actually also an AbstractArray
function JacobianConfig{D,V<:Real}(output::AbstractArray{D}, input::AbstractArray{V}, tp::InstructionTape = InstructionTape())
cfg_input = track(similar(input), D, tp)
cfg_output = track!(similar(output, TrackedReal{D,D,Void}), output, tp)
return _JacobianConfig(cfg_input, cfg_output, tp)
end

"""
ReverseDiff.JacobianConfig(result::DiffBase.DiffResult, input, tp::RawTape = RawTape())
ReverseDiff.JacobianConfig(result::DiffBase.DiffResult, input, tp::InstructionTape = InstructionTape())
A convenience method for `JacobianConfig(DiffBase.value(result), input, tp)`.
"""
JacobianConfig(result::DiffResult, input, tp::RawTape) = JacobianConfig(DiffBase.value(result), input, tp)
JacobianConfig(result::DiffResult, input, tp::InstructionTape) = JacobianConfig(DiffBase.value(result), input, tp)

#################
# HessianConfig #
Expand All @@ -129,7 +129,7 @@ immutable HessianConfig{G<:GradientConfig,J<:JacobianConfig} <: AbstractConfig
end

"""
ReverseDiff.HessianConfig(input::AbstractArray, gtp::RawTape = RawTape(), jtp::RawTape = RawTape())
ReverseDiff.HessianConfig(input::AbstractArray, gtp::InstructionTape = InstructionTape(), jtp::InstructionTape = InstructionTape())
Return a `HessianConfig` instance containing the preallocated tape and work buffers used
by the `ReverseDiff.hessian`/`ReverseDiff.hessian!` methods. `gtp` is the tape used for
Expand All @@ -139,32 +139,32 @@ Note that `input` is only used for type and shape information; it is not stored
in any way. It is assumed that the element type of `input` is same as the element type of
the target function's output.
"""
function HessianConfig(input::AbstractArray, gtp::RawTape = RawTape(), jtp::RawTape = RawTape())
function HessianConfig(input::AbstractArray, gtp::InstructionTape = InstructionTape(), jtp::InstructionTape = InstructionTape())
return HessianConfig(input, eltype(input), gtp, jtp)
end

"""
ReverseDiff.HessianConfig(input::AbstractArray, ::Type{D}, gtp::RawTape = RawTape(), jtp::RawTape = RawTape())
ReverseDiff.HessianConfig(input::AbstractArray, ::Type{D}, gtp::InstructionTape = InstructionTape(), jtp::InstructionTape = InstructionTape())
Like `HessianConfig(input, tp)`, except the provided type `D` is assumed to be the element
type of the target function's output.
"""
function HessianConfig{D}(input::AbstractArray, ::Type{D}, gtp::RawTape = RawTape(), jtp::RawTape = RawTape())
function HessianConfig{D}(input::AbstractArray, ::Type{D}, gtp::InstructionTape = InstructionTape(), jtp::InstructionTape = InstructionTape())
jcfg = JacobianConfig(input, D, jtp)
gcfg = GradientConfig(jcfg.input, gtp)
return HessianConfig(gcfg, jcfg)
end

"""
ReverseDiff.HessianConfig(result::DiffBase.DiffResult, input::AbstractArray, gtp::RawTape = RawTape(), jtp::RawTape = RawTape())
ReverseDiff.HessianConfig(result::DiffBase.DiffResult, input::AbstractArray, gtp::InstructionTape = InstructionTape(), jtp::InstructionTape = InstructionTape())
Like `HessianConfig(input, tp)`, but utilize `result` along with `input` to construct work
buffers.
Note that `result` and `input` are only used for type and shape information; they are not
stored or modified in any way.
"""
function HessianConfig(result::DiffResult, input::AbstractArray, gtp::RawTape = RawTape(), jtp::RawTape = RawTape())
function HessianConfig(result::DiffResult, input::AbstractArray, gtp::InstructionTape = InstructionTape(), jtp::InstructionTape = InstructionTape())
jcfg = JacobianConfig(DiffBase.gradient(result), input, jtp)
gcfg = GradientConfig(jcfg.input, gtp)
return HessianConfig(gcfg, jcfg)
Expand Down
10 changes: 5 additions & 5 deletions src/api/tape.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# AbstractTape #
################

abstract AbstractTape
@compat abstract type AbstractTape end

Base.show(io::IO, t::AbstractTape) = print(io, typeof(t).name, "(", t.func, ")")

Expand All @@ -15,13 +15,13 @@ for T in (:GradientTape, :JacobianTape, :HessianTape)
func::F
input::I
output::O
tape::RawTape
tape::InstructionTape
# disable default outer constructor
$(T)(func, input, output, tape) = new(func, input, output, tape)
end

# "private" convienence constructor
$(_T){F,I,O}(func::F, input::I, output::O, tape::RawTape) = $(T){F,I,O}(func, input, output, tape)
$(_T){F,I,O}(func::F, input::I, output::O, tape::InstructionTape) = $(T){F,I,O}(func, input, output, tape)

Base.length(t::$T) = length(t.tape)

Expand Down Expand Up @@ -74,7 +74,7 @@ Base.length(ct::CompiledTape) = length(ct.tape)

@inline output_hook(ct::CompiledTape) = output_hook(ct.tape)

function generate_forward_pass_method{T}(::Type{T}, tape::RawTape)
function generate_forward_pass_method{T}(::Type{T}, tape::InstructionTape)
body = Expr(:block)
push!(body.args, :(tape = compiled_tape.tape.tape))
for i in 1:length(tape)
Expand All @@ -84,7 +84,7 @@ function generate_forward_pass_method{T}(::Type{T}, tape::RawTape)
return :(ReverseDiff.forward_pass!(compiled_tape::$T) = $body)
end

function generate_reverse_pass_method{T}(::Type{T}, tape::RawTape)
function generate_reverse_pass_method{T}(::Type{T}, tape::InstructionTape)
body = Expr(:block)
push!(body.args, :(tape = compiled_tape.tape.tape))
for i in length(tape):-1:1
Expand Down
83 changes: 49 additions & 34 deletions src/tape.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,11 @@
# AbstractInstruction #
#######################

abstract AbstractInstruction

typealias RawTape Vector{AbstractInstruction}

# Define some AbstractInstruction types. They all have the same structure,
# but are defined this way to make dispatch more readable (and possibly
# faster) than dispatching on a type parameter.
for InstructionType in (:ScalarInstruction, :SpecialInstruction)
_InstructionType = Symbol(string("_", InstructionType))
@eval begin
immutable $(InstructionType){F,I,O,C} <: AbstractInstruction
func::F
input::I
output::O
cache::C
# disable default outer constructor
$(InstructionType)(func, input, output, cache) = new(func, input, output, cache)
end

@inline function $(_InstructionType){F,I,O,C}(func::F, input::I, output::O, cache::C)
return $(InstructionType){F,I,O,C}(func, input, output, cache)
end

function $(InstructionType)(func, input, output, cache = nothing)
return $(_InstructionType)(func, capture(input), capture(output), cache)
end
end
end
@compat abstract type AbstractInstruction end

@compat const InstructionTape = Vector{AbstractInstruction}

function record!{InstructionType}(tp::RawTape, ::Type{InstructionType}, args...)
function record!{InstructionType}(tp::InstructionTape, ::Type{InstructionType}, args...)
tp !== NULL_TAPE && push!(tp, InstructionType(args...))
return nothing
end
Expand All @@ -49,11 +24,51 @@ end
@inline capture(state) = state
@inline capture(state::Tuple) = map(capture, state)

# ScalarInstruction #
#-------------------#

immutable ScalarInstruction{F,I,O,C} <: AbstractInstruction
func::F
input::I
output::O
cache::C
# disable default outer constructor
(::Type{ScalarInstruction{F,I,O,C}}){F,I,O,C}(func::F, input::I, output::O, cache::C) = new(func, input, output, cache)
end

@inline function _ScalarInstruction{F,I,O,C}(func::F, input::I, output::O, cache::C)
return ScalarInstruction{F,I,O,C}(func, input, output, cache)
end

function ScalarInstruction(func, input, output, cache = nothing)
return _ScalarInstruction(func, capture(input), capture(output), cache)
end

# SpecialInstruction #
#--------------------#

immutable SpecialInstruction{F,I,O,C} <: AbstractInstruction
func::F
input::I
output::O
cache::C
# disable default outer constructor
(::Type{SpecialInstruction{F,I,O,C}}){F,I,O,C}(func::F, input::I, output::O, cache::C) = new(func, input, output, cache)
end

@inline function _SpecialInstruction{F,I,O,C}(func::F, input::I, output::O, cache::C)
return SpecialInstruction{F,I,O,C}(func, input, output, cache)
end

function SpecialInstruction(func, input, output, cache = nothing)
return _SpecialInstruction(func, capture(input), capture(output), cache)
end

##########
# passes #
##########

function forward_pass!(tape::RawTape)
function forward_pass!(tape::InstructionTape)
for instruction in tape
forward_exec!(instruction)
end
Expand All @@ -63,7 +78,7 @@ end
@noinline forward_exec!(instruction::ScalarInstruction) = scalar_forward_exec!(instruction)
@noinline forward_exec!(instruction::SpecialInstruction) = special_forward_exec!(instruction)

function reverse_pass!(tape::RawTape)
function reverse_pass!(tape::InstructionTape)
for i in length(tape):-1:1
reverse_exec!(tape[i])
end
Expand All @@ -90,10 +105,10 @@ function Base.show(io::IO, instruction::AbstractInstruction, pad = "")
print(io, pad, " cache: ", compactrepr(instruction.cache))
end

Base.display(tp::RawTape) = show(STDOUT, tp)
Base.display(tp::InstructionTape) = show(STDOUT, tp)

function Base.show(io::IO, tp::RawTape)
println("$(length(tp))-element RawTape:")
function Base.show(io::IO, tp::InstructionTape)
println("$(length(tp))-element InstructionTape:")
i = 1
for instruction in tp
print(io, "$i => ")
Expand Down
Loading

0 comments on commit e54c6cd

Please sign in to comment.