# Which direction: DifferentiatonInterface, Enzyme, Zygote with CUDA and FFTs?

**URL:** <https://discourse.julialang.org/t/which-direction-differentiatoninterface-enzyme-zygote-with-cuda-and-ffts/132225>\
**Category:** General Usage\
**Tags:** ad\
**Created:** [September 9, 2025, 10:22am UTC](https://discourse.julialang.org/t/which-direction-differentiatoninterface-enzyme-zygote-with-cuda-and-ffts/132225 "2025-09-09T10:22:32Z")\
**Posts on this page:** 1\
**Page:** 2

<div class="post-metadata">

**Author:** ![roflmaostc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/roflmaostc/32/30123_2.png) [@roflmaostc](https://discourse.julialang.org/u/roflmaostc)\
**Post date:** [September 17, 2025, 6:51am UTC](https://discourse.julialang.org/t/which-direction-differentiatoninterface-enzyme-zygote-with-cuda-and-ffts/132225/21 "2025-09-17T06:51:26Z")

</div>

Sorry, to be precise: I meant it’s better to use the FFT plan instead of `bfft`, especially with CUDA this usually allocates a lot of memory.

Something along the lines like this:

```julia-auto
    ....
    Pt = P' # using the plan instead of bfft
    scale = P.scale
    project_x = ChainRulesCore.ProjectTo(x)
    project_scale = ChainRulesCore.ProjectTo(scale)
    function mul_scaledplan_pullback(ȳ)
        x̄ = ChainRulesCore.@thunk(project_x(Pt * ȳ))
        scale_tangent = ChainRulesCore.@thunk(project_scale(AbstractFFTs.dot(y, ȳ) / conj(scale)))
        plan_tangent = ChainRulesCore.Tangent{typeof(P)}(;p=ChainRulesCore.NoTangent(), scale=scale_tangent)
        ...

```

Source

> <https://github.com/JuliaMath/AbstractFFTs.jl/blob/04a14f5a3491697d9b5a6e17ffa994cf82ce2ab0/ext/AbstractFFTsChainRulesCoreExt.jl#L211C4-L216C55>

[Previous page](https://discourse.julialang.org/t/which-direction-differentiatoninterface-enzyme-zygote-with-cuda-and-ffts/132225.md?page=1)
