# BatchDuplicated functions in Enzyme

**URL:** <https://discourse.julialang.org/t/batchduplicated-functions-in-enzyme/119001>\
**Category:** Machine Learning\
**Tags:** enzyme\
**Created:** [September 3, 2024, 5:18pm UTC](https://discourse.julialang.org/t/batchduplicated-functions-in-enzyme/119001 "2024-09-03T17:18:37Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [September 3, 2024, 5:18pm UTC](https://discourse.julialang.org/t/batchduplicated-functions-in-enzyme/119001/1 "2024-09-03T17:18:37Z")

</div>

I’m using Enzyme to differentiate through a closure, and `BatchDuplicated` on the closure itself doesn’t seem to work, unlike `Duplicated`.

```julia
using Enzyme

struct MyClosure{A}
    a::A
end

function (mc::MyClosure)(x)
    # computes x^2 using internal storage
    mc.a[1] = x
    return mc.a[1]^2
end

g = MyClosure([0.0])
g(3.0) # 9.0

g_and_dg = Duplicated(g, make_zero(g))
x_and_dx = Duplicated(3.0, 5.0)
autodiff(Forward, g_and_dg, Duplicated, x_and_dx) # (9.0, 30.0)

g_and_dgs = BatchDuplicated(g, (make_zero(g), make_zero(g)))
x_and_dxs = BatchDuplicated(3.0, (5.0, 7.0))
autodiff(Forward, g_and_dgs, BatchDuplicated, x_and_dxs) # error

```

The last call triggers the following error:

```julia
ERROR: TypeError: in ccall argument 3, expected MyClosure{Vector{Float64}}, got a value of type Tuple{MyClosure{Vector{Float64}}, MyClosure{Vector{Float64}}}
Stacktrace:
 [1] macro expansion
   @ ~/.julia/packages/Enzyme/Tb3Iu/src/compiler.jl:7151 [inlined]
 [2] enzyme_call
   @ ~/.julia/packages/Enzyme/Tb3Iu/src/compiler.jl:6760 [inlined]
 [3] ForwardModeThunk
   @ ~/.julia/packages/Enzyme/Tb3Iu/src/compiler.jl:6640 [inlined]
 [4] autodiff(::ForwardMode{…}, f::BatchDuplicated{…}, ::Type{…}, args::BatchDuplicated{…})
   @ Enzyme ~/.julia/packages/Enzyme/Tb3Iu/src/Enzyme.jl:437
 [5] top-level scope
Some type information was truncated. Use `show(err)` to see complete types.

```

@wsmoses do you have any clue what I did wrong? For reference, it happened in [this PR](https://github.com/gdalle/DifferentiationInterface.jl/pull/446).

---

<div class="post-metadata">

**Author:** ![wsmoses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsmoses/32/26497_2.png) [@wsmoses](https://discourse.julialang.org/u/wsmoses)\
**Post date:** [September 3, 2024, 6:14pm UTC](https://discourse.julialang.org/t/batchduplicated-functions-in-enzyme/119001/2 "2024-09-03T18:14:43Z")

</div>

Seems like no one has ever used batched forward mode closures before, open an issue?

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [September 3, 2024, 6:18pm UTC](https://discourse.julialang.org/t/batchduplicated-functions-in-enzyme/119001/3 "2024-09-03T18:18:50Z")

</div>

> <https://github.com/EnzymeAD/Enzyme.jl/issues/1783>
>
> I’m using Enzyme to differentiate through a closure, and \`BatchDuplicated\` on th…e closure itself doesn’t seem to work, unlike \`Duplicated\`.
> 
> \`\`\`julia
> using Enzyme
> 
> struct MyClosure{A}
> a::A
> end
> 
> function (mc::MyClosure)(x)
> # computes x^2 using internal storage
> mc.a\[1\] = x
> return mc.a\[1\]^2
> end
> 
> g = MyClosure(\[0.0\])
> g(3.0) # 9.0
> 
> g\_and\_dg = Duplicated(g, make\_zero(g))
> x\_and\_dx = Duplicated(3.0, 5.0)
> autodiff(Forward, g\_and\_dg, Duplicated, x\_and\_dx) # (9.0, 30.0)
> 
> g\_and\_dgs = BatchDuplicated(g, (make\_zero(g), make\_zero(g)))
> x\_and\_dxs = BatchDuplicated(3.0, (5.0, 7.0))
> autodiff(Forward, g\_and\_dgs, BatchDuplicated, x\_and\_dxs) # error
> \`\`\`
> 
> The last call triggers the following error:
> 
> \`\`\`julia
> ERROR: TypeError: in ccall argument 3, expected MyClosure{Vector{Float64}}, got a value of type Tuple{MyClosure{Vector{Float64}}, MyClosure{Vector{Float64}}}
> Stacktrace:
> \[1\] macro expansion
> @ ~/.julia/packages/Enzyme/Tb3Iu/src/compiler.jl:7151 \[inlined\]
> \[2\] enzyme\_call
> @ ~/.julia/packages/Enzyme/Tb3Iu/src/compiler.jl:6760 \[inlined\]
> \[3\] ForwardModeThunk
> @ ~/.julia/packages/Enzyme/Tb3Iu/src/compiler.jl:6640 \[inlined\]
> \[4\] autodiff(::ForwardMode{…}, f::BatchDuplicated{…}, ::Type{…}, args::BatchDuplicated{…})
> @ Enzyme ~/.julia/packages/Enzyme/Tb3Iu/src/Enzyme.jl:437
> \[5\] top-level scope
> Some type information was truncated. Use \`show(err)\` to see complete types.
> \`\`\`

---

<div class="post-metadata">

**Author:** ![wsmoses](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wsmoses/32/26497_2.png) [@wsmoses](https://discourse.julialang.org/u/wsmoses)\
**Post date:** [September 3, 2024, 7:21pm UTC](https://discourse.julialang.org/t/batchduplicated-functions-in-enzyme/119001/4 "2024-09-03T19:21:34Z")

</div>

Fix here: [Handle batch closures by wsmoses · Pull Request #1784 · EnzymeAD/Enzyme.jl · GitHub](https://github.com/EnzymeAD/Enzyme.jl/pull/1784)
