Skip to content

Commit

Permalink
Add EnzymeCore
Browse files Browse the repository at this point in the history
  • Loading branch information
vchuravy committed Oct 8, 2022
1 parent 76c7b08 commit 4164393
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 126 deletions.
51 changes: 48 additions & 3 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,66 @@ steps:
plugins:
- JuliaCI/julia#v1:
version: "1.6"
- JuliaCI/julia-test#v1: ~
agents:
queue: "juliagpu"
cuda: "*"
if: build.message !~ /\[skip tests\]/
timeout_in_minutes: 60
commands: |
echo "--- Setup Julia packages"
julia --color=yes --project=. -e '
import Pkg
Pkg.develop(; path = joinpath(pwd(), "lib", "EnzymeCore"))
'
echo "+++ Run tests"
julia --color=yes --project=. -e '
import Pkg
Pkg.test("Enzyme")
'
steps:
- label: "Julia v1.7"
plugins:
- JuliaCI/julia#v1:
version: "1.7"
agents:
queue: "juliagpu"
cuda: "*"
if: build.message !~ /\[skip tests\]/
timeout_in_minutes: 60
commands: |
echo "--- Setup Julia packages"
julia --color=yes --project=. -e '
import Pkg
Pkg.develop(; path = joinpath(pwd(), "lib", "EnzymeCore"))
'
echo "+++ Run tests"
julia --color=yes --project=. -e '
import Pkg
Pkg.test("Enzyme")
'
steps:
- label: "Julia v1"
plugins:
- JuliaCI/julia#v1:
version: "1"
- JuliaCI/julia-test#v1: ~
agents:
queue: "juliagpu"
cuda: "*"
if: build.message !~ /\[skip tests\]/
timeout_in_minutes: 60
timeout_in_minutes: 60
commands: |
echo "--- Setup Julia packages"
julia --color=yes --project=. -e '
import Pkg
Pkg.develop(; path = joinpath(pwd(), "lib", "EnzymeCore"))
'
echo "+++ Run tests"
julia --color=yes --project=. -e '
import Pkg
Pkg.test("Enzyme")
'
8 changes: 7 additions & 1 deletion .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,11 @@ jobs:
${{ runner.os }}-test-${{ env.cache-name }}-
${{ runner.os }}-test-
${{ runner.os }}-
- uses: julia-actions/julia-buildpkg@v1
- name: add EnzymeCore
shell: julia --color=yes --project=. {0}
run: |
using Pkg
Pkg.develop(path="lib/EnzymeCore")
- name: Build libEnzyme
if: ${{ matrix.libEnzyme == 'local' && matrix.os != 'macOS-latest'}}
run: |
Expand All @@ -86,6 +90,7 @@ jobs:
julia --project=deps -e 'using Pkg; Pkg.instantiate()'
SDKROOT=`xcrun --show-sdk-path` julia --project=deps deps/build_local.jl
cp LocalPreferences.toml test/
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v1
Expand All @@ -102,6 +107,7 @@ jobs:
- run: |
julia --project=docs -e '
using Pkg
Pkg.develop(path="lib/EnzymeCore")
Pkg.develop(PackageSpec(path=pwd()))
Pkg.instantiate()'
- run: |
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/scripts_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ jobs:
- run: |
julia --project=docs -e '
using Pkg
Pkg.develop(path="lib/EnzymeCore")
Pkg.develop(PackageSpec(path=pwd()))
Pkg.instantiate()'
- run: |
Expand Down
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ authors = ["William Moses <wmoses@mit.edu>", "Valentin Churavy <vchuravy@mit.edu
version = "0.10.10"

[deps]
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82"
EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869"
Enzyme_jll = "7cc45869-7501-5eee-bdea-0790c847d4ef"
GPUCompiler = "61eb1bfa-7361-4325-ad38-22787b887f55"
LLVM = "929cbde3-209d-540e-8aea-75f648917ca0"
Expand All @@ -16,7 +16,7 @@ Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[compat]
Adapt = "3.3"
EnzymeCore = "0.1"
CEnum = "0.4"
Enzyme_jll = "0.0.42"
GPUCompiler = "0.16.2"
Expand Down
11 changes: 11 additions & 0 deletions lib/EnzymeCore/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name = "EnzymeCore"
uuid = "f151be2c-9106-41f4-ab19-57ee4f262869"
authors = ["William Moses <wmoses@mit.edu>", "Valentin Churavy <vchuravy@mit.edu>"]
version = "0.1.0"

[deps]
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"

[compat]
Adapt = "3.3"
julia = "1.6"
129 changes: 129 additions & 0 deletions lib/EnzymeCore/src/EnzymeCore.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
module EnzymeCore

using Adapt

export Forward, Reverse
export Const, Active, Duplicated, DuplicatedNoNeed, BatchDuplicated, BatchDuplicatedNoNeed

function batch_size end

"""
abstract type Annotation{T}
Abstract type for [`autodiff`](@ref) function argument wrappers like
[`Const`](@ref), [`Active`](@ref) and [`Duplicated`](@ref).
"""
abstract type Annotation{T} end
Base.eltype(::Type{<:Annotation{T}}) where T = T

"""
Const(x)
Mark a function argument `x` of [`autodiff`](@ref) as constant,
Enzyme will not auto-differentiate in respect `Const` arguments.
"""
struct Const{T} <: Annotation{T}
val::T
end
Adapt.adapt_structure(to, x::Const) = Const(adapt(to, x.val))

# To deal with Const(Int) and prevent it to go to `Const{DataType}(T)`
Const(::Type{T}) where T = Const{Type{T}}(T)

"""
Active(x)
Mark a function argument `x` of [`autodiff`](@ref) as active,
Enzyme will auto-differentiate in respect `Active` arguments.
!!! note
Enzyme gradients with respect to integer values are zero.
[`Active`](@ref) will automatically convert plain integers to floating
point values, but cannot do so for integer values in tuples and structs.
"""
struct Active{T} <: Annotation{T}
val::T
end
Adapt.adapt_structure(to, x::Active) = Active(adapt(to, x.val))

Active(i::Integer) = Active(float(i))

"""
Duplicated(x, ∂f_∂x)
Mark a function argument `x` of [`autodiff`](@ref) as duplicated, Enzyme will
auto-differentiate in respect to such arguments, with `dx` acting as an
accumulator for gradients (so ``\\partial f / \\partial x`` will be *added to*)
`∂f_∂x`.
"""
struct Duplicated{T} <: Annotation{T}
val::T
dval::T
end
Adapt.adapt_structure(to, x::Duplicated) = Duplicated(adapt(to, x.val), adapt(to, x.dval))

"""
DuplicatedNoNeed(x, ∂f_∂x)
Like [`Duplicated`](@ref), except also specifies that Enzyme may avoid computing
the original result and only compute the derivative values.
"""
struct DuplicatedNoNeed{T} <: Annotation{T}
val::T
dval::T
end
Adapt.adapt_structure(to, x::DuplicatedNoNeed) = DuplicatedNoNeed(adapt(to, x.val), adapt(to, x.dval))

"""
BatchDuplicated(x, ∂f_∂xs)
Like [`Duplicated`](@ref), except contains several shadows to compute derivatives
for all at once. Argument `∂f_∂xs` should be a tuple of the several values of type `x`.
"""
struct BatchDuplicated{T,N} <: Annotation{T}
val::T
dval::NTuple{N,T}
end
Adapt.adapt_structure(to, x::BatchDuplicated) = BatchDuplicated(adapt(to, x.val), adapt(to, x.dval))

"""
BatchDuplicatedNoNeed(x, ∂f_∂xs)
Like [`DuplicatedNoNeed`](@ref), except contains several shadows to compute derivatives
for all at once. Argument `∂f_∂xs` should be a tuple of the several values of type `x`.
"""
struct BatchDuplicatedNoNeed{T,N} <: Annotation{T}
val::T
dval::NTuple{N,T}
end
batch_size(::BatchDuplicated{T,N}) where {T,N} = N
batch_size(::BatchDuplicatedNoNeed{T,N}) where {T,N} = N
Adapt.adapt_structure(to, x::BatchDuplicatedNoNeed) = BatchDuplicatedNoNeed(adapt(to, x.val), adapt(to, x.dval))

"""
abstract type Mode
Abstract type for what differentiation mode will be used.
"""
abstract type Mode end

"""
struct Reverse <: Mode
Reverse mode differentiation
"""
struct ReverseMode <: Mode
end
const Reverse = ReverseMode()

"""
struct Forward <: Mode
Forward mode differentiation
"""
struct ForwardMode <: Mode
end
const Forward = ForwardMode()

end # module EnzymeCore
Loading

0 comments on commit 4164393

Please sign in to comment.