burn_tensor/tensor/api/
autodiff.rs1use crate::{Tensor, kind::Autodiff};
2
3#[cfg(feature = "autodiff")]
4use crate::ops::BridgeTensor;
5#[cfg(feature = "autodiff")]
6use burn_backend::AutodiffBackend;
7#[cfg(feature = "autodiff")]
8use burn_dispatch::Dispatch;
9
10#[cfg(feature = "autodiff")]
11type AutodiffGradients = <Dispatch as AutodiffBackend>::Gradients;
12
13#[cfg(feature = "autodiff")]
16burn_std::obfuscate!(
17 type: AutodiffGradients,
18 module: gradients_opaque,
19 derives: [Send]
20);
21
22#[cfg(feature = "autodiff")]
24pub struct Gradients {
25 blob: gradients_opaque::Opaque,
26}
27
28#[cfg(feature = "autodiff")]
29impl Gradients {
30 pub(crate) fn from_inner(inner: AutodiffGradients) -> Self {
32 Self {
33 blob: gradients_opaque::Opaque::new(inner),
34 }
35 }
36
37 pub(crate) fn as_inner(&self) -> &AutodiffGradients {
39 self.blob.as_ref()
40 }
41
42 pub(crate) fn as_inner_mut(&mut self) -> &mut AutodiffGradients {
44 self.blob.as_mut()
45 }
46}
47
48#[cfg(feature = "autodiff")]
49impl<const D: usize> Tensor<D> {
50 pub fn backward(&self) -> Gradients {
52 backward_impl(&self.primitive)
53 }
54
55 pub fn grad(&self, grads: &Gradients) -> Option<Tensor<D>> {
61 grad_impl(&self.primitive, grads).map(Tensor::new)
62 }
63
64 pub fn grad_remove(&self, grads: &mut Gradients) -> Option<Tensor<D>> {
66 grad_remove_impl(&self.primitive, grads).map(Tensor::new)
67 }
68
69 pub fn grad_replace(&self, grads: &mut Gradients, grad: Tensor<D>) {
72 grad_replace_impl(&self.primitive, grads, grad.primitive)
73 }
74}
75
76#[cfg(feature = "autodiff")]
77fn backward_impl(p: &BridgeTensor) -> Gradients {
78 Gradients::from_inner(Dispatch::backward(p.clone().into_float()))
79}
80
81#[cfg(feature = "autodiff")]
82fn grad_impl(p: &BridgeTensor, grads: &Gradients) -> Option<BridgeTensor> {
83 Dispatch::grad(p.as_float(), grads.as_inner()).map(BridgeTensor::float)
84}
85
86#[cfg(feature = "autodiff")]
87fn grad_remove_impl(p: &BridgeTensor, grads: &mut Gradients) -> Option<BridgeTensor> {
88 Dispatch::grad_remove(p.as_float(), grads.as_inner_mut()).map(BridgeTensor::float)
89}
90
91#[cfg(feature = "autodiff")]
92fn grad_replace_impl(p: &BridgeTensor, grads: &mut Gradients, grad: BridgeTensor) {
93 Dispatch::grad_replace(p.as_float(), grads.as_inner_mut(), grad.into_float())
94}
95
96impl<const D: usize, K: Autodiff> Tensor<D, K> {
97 pub fn inner(self) -> Tensor<D, K> {
99 Tensor::new(K::inner(self.primitive))
100 }
101
102 pub fn from_inner(inner: Tensor<D, K>) -> Self {
112 Self::new(K::from_inner(inner.primitive))
113 }
114}
115
116