pub struct EagerRuntime { /* private fields */ }Expand description
Shared eager execution context for tensors on a backend.
Reusing one context lets eager tensors share backend state, extension runtime caches, and gradient storage across a computation.
§Examples
use tenferro_cpu::CpuBackend;
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let x = EagerTensor::from_tensor_in(Tensor::from_vec_col_major(vec![1], vec![1.0_f64]).unwrap(), ctx.clone()).unwrap();
let y = EagerTensor::from_tensor_in(Tensor::from_vec_col_major(vec![1], vec![2.0_f64]).unwrap(), ctx).unwrap();
let z = x.add(&y).unwrap();
assert_eq!(z.materialized().unwrap().as_slice::<f64>().unwrap(), &[3.0]);Implementations§
Source§impl EagerRuntime
impl EagerRuntime
Sourcepub fn new() -> Result<Arc<Self>>
pub fn new() -> Result<Arc<Self>>
Create a shared CPU eager execution context.
§Examples
use tenferro_ad::EagerRuntime;
let ctx = EagerRuntime::new()?;
assert_eq!(std::sync::Arc::strong_count(&ctx), 1);§Errors
Returns Error::RuntimeStateSource when provider runtime
registration cannot be configured, preserving the underlying
[RuntimeConfigError] as the typed error source.
Sourcepub fn with_cpu_backend(backend: CpuBackend) -> Result<Arc<Self>>
pub fn with_cpu_backend(backend: CpuBackend) -> Result<Arc<Self>>
Create a shared eager execution context from a configured CPU backend.
§Examples
use tenferro_cpu::CpuBackend;
use tenferro_ad::{EagerRuntime};
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::with_threads(1)?)?;
assert_eq!(std::sync::Arc::strong_count(&ctx), 1);§Errors
Returns Error::RuntimeStateSource when provider runtime
registration cannot be configured, preserving the underlying
[RuntimeConfigError] as the typed error source.
Sourcepub fn on_cpu(
self: &Arc<Self>,
placement: CpuPlacement,
) -> Result<CpuPlacementBoundEager>
pub fn on_cpu( self: &Arc<Self>, placement: CpuPlacement, ) -> Result<CpuPlacementBoundEager>
Snapshot a placement-selected CPU handle from this eager runtime.
The eager backend lock is held only long enough to verify the backend kind and clone its CPU coordinator/provider snapshot. Placement resolution happens after that guard is dropped. The returned value does not hold a resource permit or a second runtime/backend mutex while idle.
§Examples
use tenferro_ad::EagerRuntime;
use tenferro_cpu::CpuPlacement;
let runtime = EagerRuntime::new()?;
let cpu = runtime.on_cpu(CpuPlacement::Auto)?;
assert_eq!(cpu.runtime_id(), runtime.id());§Errors
Returns Error::RuntimeState if the eager backend lock is poisoned,
Error::Unsupported if the runtime is not CPU-backed, or a typed
tensor runtime error retaining [tenferro_cpu::CpuPlacementError] when
the requested placement cannot be resolved.
Sourcepub fn with_cpu_backend_and_ad_context(
backend: CpuBackend,
ad: &AdContext,
) -> Result<Arc<Self>>
pub fn with_cpu_backend_and_ad_context( backend: CpuBackend, ad: &AdContext, ) -> Result<Arc<Self>>
Create a shared CPU eager context with explicit AD extension rules.
§Examples
use tenferro_cpu::CpuBackend;
use tenferro_ad::{AdContext, EagerRuntime};
let ad = AdContext::builder().build().unwrap();
let ctx = EagerRuntime::with_cpu_backend_and_ad_context(CpuBackend::new(), &ad)?;
assert_eq!(std::sync::Arc::strong_count(&ctx), 1);§Errors
Returns Error::RuntimeStateSource when provider runtime
registration cannot be configured, preserving the underlying
[RuntimeConfigError] as the typed error source.
Sourcepub fn id(&self) -> ContextId
pub fn id(&self) -> ContextId
Return an opaque identifier for this context.
§Examples
use tenferro_cpu::CpuBackend;
use tenferro_ad::{EagerRuntime};
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
assert_ne!(ctx.id(), EagerRuntime::with_cpu_backend(CpuBackend::new())?.id());Sourcepub fn no_grad(&self) -> EagerNoGradGuard
pub fn no_grad(&self) -> EagerNoGradGuard
Disable eager operation recording on the current thread until the guard is dropped.
This is useful for optimizer updates, metric calculations, and other eager computations that should not become part of the AD tape.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![1], vec![3.0_f64]).unwrap(),
ctx.clone(),
)?;
let y = {
let _guard = ctx.no_grad();
x.mul(&x)?
};
assert!(!y.tracks_grad());Sourcepub fn install_extension_module(
&self,
module: Arc<dyn ExtensionModule>,
) -> Result<RuntimeEpoch>
pub fn install_extension_module( &self, module: Arc<dyn ExtensionModule>, ) -> Result<RuntimeEpoch>
Install or replace one extension module on this eager context’s runtime.
Eager extension wrappers call this as an idempotent “ensure installed” step. The eager context serializes this path so parallel first-use of the same extension family cannot publish over another thread’s base snapshot.
§Errors
Returns tenferro_runtime::Error::RuntimeState when runtime
reconfiguration fails or the extension module transaction is invalid.
Sourcepub fn clear_extension_caches(&self) -> Result<()>
pub fn clear_extension_caches(&self) -> Result<()>
Clear generic extension runtime cache entries.
§Examples
use tenferro_cpu::CpuBackend;
use tenferro_ad::{EagerRuntime};
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
ctx.clear_extension_caches()?;
assert_eq!(ctx.cache_stats()?.extensions.entries, 0);§Errors
Returns tenferro_runtime::Error::RuntimeState when the extension
cache lock is poisoned.
Sourcepub fn clear_caches(&self) -> Result<()>
pub fn clear_caches(&self) -> Result<()>
Clear every cache owned by this eager context.
§Examples
use tenferro_cpu::CpuBackend;
use tenferro_ad::{EagerRuntime};
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
ctx.clear_caches()?;
assert_eq!(ctx.cache_stats()?.extensions.entries, 0);
assert_eq!(ctx.cache_stats()?.ad_transforms.entries, 0);
assert_eq!(ctx.cache_stats()?.prepared_derivatives.entries, 0);§Errors
Returns tenferro_runtime::Error::RuntimeState when either the
extension cache or AD-transform cache is poisoned.
Sourcepub fn clear_prepared_derivative_cache(&self) -> Result<()>
pub fn clear_prepared_derivative_cache(&self) -> Result<()>
Clear prepared derivative program cache entries.
§Examples
use tenferro_ad::EagerRuntime;
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
ctx.clear_prepared_derivative_cache()?;
assert_eq!(ctx.cache_stats()?.prepared_derivatives.entries, 0);§Errors
Returns tenferro_runtime::Error::RuntimeState if the prepared
derivative cache lock is poisoned.
Sourcepub fn cache_stats(&self) -> Result<EagerRuntimeCacheStats>
pub fn cache_stats(&self) -> Result<EagerRuntimeCacheStats>
Return eager runtime cache-entry and retained-byte stats.
§Examples
use tenferro_cpu::CpuBackend;
use tenferro_ad::{EagerRuntime};
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let stats = ctx.cache_stats()?;
assert_eq!(stats.extensions.entries, 0);
assert_eq!(stats.ad_transforms.entries, 0);
assert_eq!(stats.prepared_derivatives.entries, 0);§Errors
Returns tenferro_runtime::Error::RuntimeState when a cache or
AD-transform cache lock is poisoned.
Sourcepub fn ad_transform_cache_limits(&self) -> Result<AdTransformCacheLimits>
pub fn ad_transform_cache_limits(&self) -> Result<AdTransformCacheLimits>
Return the AD transform cache retention limits.
§Examples
use tenferro_ad::EagerRuntime;
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
assert!(ctx.ad_transform_cache_limits()?.max_entries().get() > 0);§Errors
Returns tenferro_runtime::Error::RuntimeState if the AD-transform
cache lock is poisoned.
Sourcepub fn set_ad_transform_cache_limits(
&self,
limits: AdTransformCacheLimits,
) -> Result<()>
pub fn set_ad_transform_cache_limits( &self, limits: AdTransformCacheLimits, ) -> Result<()>
Replace AD transform cache retention limits.
§Examples
use std::num::NonZeroUsize;
use tenferro_ad::{AdTransformCacheLimits, EagerRuntime};
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let limits = AdTransformCacheLimits::new(NonZeroUsize::new(1).unwrap());
ctx.set_ad_transform_cache_limits(limits)?;
assert_eq!(ctx.ad_transform_cache_limits()?, limits);§Errors
Returns tenferro_runtime::Error::RuntimeState if the AD-transform
cache lock is poisoned while updating limits.
Sourcepub fn clear_ad_transform_caches(&self) -> Result<()>
pub fn clear_ad_transform_caches(&self) -> Result<()>
Clear AD transform cache entries visible through this eager runtime.
§Examples
use tenferro_ad::EagerRuntime;
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
ctx.clear_ad_transform_caches()?;
assert_eq!(ctx.cache_stats()?.ad_transforms.entries, 0);§Errors
Returns tenferro_runtime::Error::RuntimeState if the AD-transform
cache lock is poisoned while clearing entries.
Sourcepub fn prepared_derivative_cache_limits(&self) -> Result<AdTransformCacheLimits>
pub fn prepared_derivative_cache_limits(&self) -> Result<AdTransformCacheLimits>
Return prepared derivative cache retention limits.
§Examples
use tenferro_ad::EagerRuntime;
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
assert!(ctx.prepared_derivative_cache_limits()?.max_entries().get() > 0);§Errors
Returns tenferro_runtime::Error::RuntimeState if the prepared
derivative cache lock is poisoned.
Sourcepub fn set_prepared_derivative_cache_limits(
&self,
limits: AdTransformCacheLimits,
) -> Result<()>
pub fn set_prepared_derivative_cache_limits( &self, limits: AdTransformCacheLimits, ) -> Result<()>
Replace prepared derivative cache retention limits.
§Examples
use std::num::NonZeroUsize;
use tenferro_ad::{AdTransformCacheLimits, EagerRuntime};
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let limits = AdTransformCacheLimits::new(NonZeroUsize::new(1).unwrap());
ctx.set_prepared_derivative_cache_limits(limits)?;
assert_eq!(ctx.prepared_derivative_cache_limits()?, limits);§Errors
Returns tenferro_runtime::Error::RuntimeState if the prepared
derivative cache lock is poisoned.
Sourcepub fn extension_cache_limits(&self) -> Result<ExtensionCacheLimits>
pub fn extension_cache_limits(&self) -> Result<ExtensionCacheLimits>
Return the extension cache retention limits.
§Errors
Returns tenferro_runtime::Error::RuntimeState if the extension
cache lock is poisoned.
Sourcepub fn set_extension_cache_limits(
&self,
limits: ExtensionCacheLimits,
) -> Result<()>
pub fn set_extension_cache_limits( &self, limits: ExtensionCacheLimits, ) -> Result<()>
Replace extension cache retention limits.
§Errors
Returns tenferro_runtime::Error::RuntimeState if the extension
cache lock is poisoned.
Sourcepub fn with_execution_session<R: Send>(
&self,
f: impl FnOnce(&mut dyn BackendSession) -> R + Send,
) -> Result<R>
pub fn with_execution_session<R: Send>( &self, f: impl FnOnce(&mut dyn BackendSession) -> R + Send, ) -> Result<R>
Enter one backend execution session and run provider-neutral operations.
The callback receives only a lifetime-bound, non-owning backend session. The backend and its engine registration are fixed when the eager runtime is constructed. Extension modules are installed separately and remain available to later extension operations.
§Examples
use tenferro_ad::EagerRuntime;
use tenferro_cpu::CpuBackend;
use tenferro_tensor::{Tensor, TensorElementwise};
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let lhs = Tensor::from_vec_col_major(vec![1], vec![1.0_f64])?;
let rhs = Tensor::from_vec_col_major(vec![1], vec![2.0_f64])?;
let output = ctx.with_execution_session(|session| {
TensorElementwise::add(session, &lhs, &rhs)
})??;
assert_eq!(output.as_slice::<f64>()?, &[3.0]);§Errors
Returns tenferro_runtime::Error::RuntimeState if the eager backend
lock is poisoned. Backend operations retain their typed tensor/backend
errors inside the callback result.
Sourcepub fn with_extension_execution_context<R: Send>(
&self,
f: impl FnOnce(&mut ExtensionExecutionContext<'_, dyn BackendSession + '_>) -> R + Send,
) -> Result<R>
pub fn with_extension_execution_context<R: Send>( &self, f: impl FnOnce(&mut ExtensionExecutionContext<'_, dyn BackendSession + '_>) -> R + Send, ) -> Result<R>
Run an extension-owned eager operation with a borrowed backend session and the eager runtime’s extension cache store.
The eager backend owner is locked before the extension-cache lock is
acquired. The callback receives an
tenferro_runtime::ExtensionExecutionContext so cache access and
backend execution share one lifetime-bound context without exposing the
owning eager backend. The backend and its engine registration remain
fixed for the eager runtime’s lifetime.
§Examples
use tenferro_ad::EagerRuntime;
use tenferro_cpu::CpuBackend;
use tenferro_tensor::{Tensor, TensorElementwise};
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let lhs = Tensor::from_vec_col_major(vec![1], vec![1.0_f64])?;
let rhs = Tensor::from_vec_col_major(vec![1], vec![2.0_f64])?;
let output = ctx.with_extension_execution_context(|extension_ctx| {
TensorElementwise::add(extension_ctx.backend_mut(), &lhs, &rhs)
})??;
assert_eq!(output.as_slice::<f64>()?, &[3.0]);§Errors
Returns tenferro_runtime::Error::RuntimeState if the eager backend
or extension-cache lock is poisoned. Errors returned by the callback
remain in its result value.
Sourcepub fn synchronize(&self) -> Result<()>
pub fn synchronize(&self) -> Result<()>
Block the current thread until backend work submitted by this eager runtime completes.
CPU runtimes return immediately. CUDA and WebGPU runtimes synchronize their current backend work queue.
§Examples
use tenferro_cpu::CpuBackend;
use tenferro_ad::EagerRuntime;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
ctx.synchronize().unwrap();§Errors
Returns tenferro_runtime::Error::RuntimeState if the backend lock is
poisoned, or a typed tensor backend error if synchronization fails.
Sourcepub fn clear_grads(&self) -> Result<()>
pub fn clear_grads(&self) -> Result<()>
Clear all live gradient slots tracked by this context.
This resets the stored gradients to None without unregistering the
tensors, so future backward() calls can accumulate again.
§Examples
use tenferro_cpu::CpuBackend;
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let x = EagerTensor::requires_grad_in(Tensor::from_vec_col_major(vec![3], vec![1.0_f64, 2.0, 3.0]).unwrap(), ctx.clone()).unwrap();
let y = EagerTensor::requires_grad_in(Tensor::from_vec_col_major(vec![3], vec![4.0_f64, 5.0, 6.0]).unwrap(), ctx.clone()).unwrap();
let loss = x.mul(&y).unwrap().reduce_sum(Some(&[0])).unwrap();
let _ = loss.backward().unwrap();
ctx.clear_grads()?;
assert!(x.grad()?.is_none());
assert!(y.grad()?.is_none());§Errors
Returns tenferro_runtime::Error::RuntimeState if a gradient-slot
lock is poisoned while clearing live gradients.
Sourcepub fn constant_from(self: &Arc<Self>, tensor: Tensor) -> Result<EagerTensor>
pub fn constant_from(self: &Arc<Self>, tensor: Tensor) -> Result<EagerTensor>
Import a concrete tensor into this context as an untracked constant.
The returned tensor does not participate in gradient tracking. Use this for fixed masks, quadrature weights, physical constants, and other data that should not receive gradients.
§Examples
use tenferro_cpu::CpuBackend;
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let c = ctx.constant_from(Tensor::from_vec_col_major(vec![2], vec![1.0_f64, 2.0]).unwrap())?;
let x = EagerTensor::requires_grad_in(Tensor::from_vec_col_major(vec![2], vec![3.0_f64, 4.0]).unwrap(), ctx)?;
let z = x.add(&c).unwrap();
assert_eq!(z.materialized()?.as_slice::<f64>().unwrap(), &[4.0, 6.0]);§Errors
Returns tenferro_runtime::Error::RuntimeState when metadata cannot
be registered or the backend lock is poisoned.
Sourcepub fn variable_from(self: &Arc<Self>, tensor: Tensor) -> Result<EagerTensor>
pub fn variable_from(self: &Arc<Self>, tensor: Tensor) -> Result<EagerTensor>
Import a concrete tensor into this context as a trainable variable.
The returned tensor participates in gradient tracking; its gradient slot is registered in this context.
§Examples
use tenferro_cpu::CpuBackend;
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let p = ctx.variable_from(Tensor::from_vec_col_major(vec![2], vec![1.0_f64, 2.0]).unwrap())?;
let loss = p.exp().unwrap().reduce_sum(Some(&[0])).unwrap();
let _ = loss.backward().unwrap();
let grad = p.grad().unwrap().unwrap();
assert_eq!(grad.shape(), &[2]);§Errors
Returns tenferro_runtime::Error::RuntimeState when gradient metadata
or the eager backend state cannot be registered.
Sourcepub fn grad(
self: &Arc<Self>,
output: &EagerTensor,
wrt: &EagerTensor,
) -> Result<EagerTensor>
pub fn grad( self: &Arc<Self>, output: &EagerTensor, wrt: &EagerTensor, ) -> Result<EagerTensor>
Gradient of a scalar eager output with respect to an eager tensor.
Functional eager gradients return ordinary eager tensors and do not
write into grad() slots. The returned tensor keeps a trace when the
derivative computation depends on tracked eager values.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![], vec![3.0_f64]).unwrap(),
ctx.clone(),
)?;
let loss = x.mul(&x)?;
let dx = ctx.grad(&loss, &x)?;
assert_eq!(dx.materialized()?.as_slice::<f64>().unwrap(), &[6.0]);§Errors
Returns tenferro_runtime::Error::NonScalarGrad for a non-scalar
output, Error::ContextMismatch for tensors from another runtime,
Error::UnsupportedAdRule when an AD rule is unavailable, or a typed
validation/backend error from eager execution.
Sourcepub fn grad_optional(
self: &Arc<Self>,
output: &EagerTensor,
wrt: &EagerTensor,
) -> Result<Option<EagerTensor>>
pub fn grad_optional( self: &Arc<Self>, output: &EagerTensor, wrt: &EagerTensor, ) -> Result<Option<EagerTensor>>
Gradient that returns None when wrt is inactive.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![], vec![3.0_f64]).unwrap(),
ctx.clone(),
)?;
let y = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![], vec![4.0_f64]).unwrap(),
ctx.clone(),
)?;
let loss = y.mul(&y)?;
assert!(ctx.grad_optional(&loss, &x)?.is_none());§Errors
Returns tenferro_runtime::Error::NonScalarGrad for a non-scalar
output, Error::ContextMismatch for a foreign runtime, or a typed
validation/backend/runtime-state error from eager execution.
Sourcepub fn vjp(
self: &Arc<Self>,
output: &EagerTensor,
wrt: &EagerTensor,
cotangent: &EagerTensor,
) -> Result<EagerTensor>
pub fn vjp( self: &Arc<Self>, output: &EagerTensor, wrt: &EagerTensor, cotangent: &EagerTensor, ) -> Result<EagerTensor>
Reverse-mode vector-Jacobian product for eager tensors.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![2], vec![2.0_f64, 3.0]).unwrap(),
ctx.clone(),
)?;
let y = x.mul(&x)?;
let seed = EagerTensor::from_tensor_in(
Tensor::from_vec_col_major(vec![2], vec![1.0_f64, 1.0]).unwrap(),
ctx.clone(),
)?;
let dx = ctx.vjp(&y, &x, &seed)?;
assert_eq!(dx.materialized()?.as_slice::<f64>().unwrap(), &[4.0, 6.0]);§Errors
Returns Error::ContextMismatch for tensors from different eager
runtimes, Error::Validation when the cotangent shape or dtype does
not match the output, Error::UnsupportedAdRule when a rule is not
registered, or a typed backend/runtime-state error.
Sourcepub fn vjp_optional(
self: &Arc<Self>,
output: &EagerTensor,
wrt: &EagerTensor,
cotangent: &EagerTensor,
) -> Result<Option<EagerTensor>>
pub fn vjp_optional( self: &Arc<Self>, output: &EagerTensor, wrt: &EagerTensor, cotangent: &EagerTensor, ) -> Result<Option<EagerTensor>>
Reverse-mode vector-Jacobian product that returns None for inactive inputs.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![1], vec![2.0_f64]).unwrap(),
ctx.clone(),
)?;
let y = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![1], vec![4.0_f64]).unwrap(),
ctx.clone(),
)?;
let seed = EagerTensor::from_tensor_in(
Tensor::from_vec_col_major(vec![1], vec![1.0_f64]).unwrap(),
ctx.clone(),
)?;
let loss = y.mul(&y)?;
assert!(ctx.vjp_optional(&loss, &x, &seed)?.is_none());§Errors
Returns Error::ContextMismatch for tensors from different eager
runtimes, Error::Validation when the cotangent shape or dtype does
not match the output, Error::UnsupportedAdRule when a rule is not
registered, or a typed backend/runtime-state error.
Sourcepub fn jvp(
self: &Arc<Self>,
output: &EagerTensor,
wrt: &EagerTensor,
tangent: &EagerTensor,
) -> Result<EagerTensor>
pub fn jvp( self: &Arc<Self>, output: &EagerTensor, wrt: &EagerTensor, tangent: &EagerTensor, ) -> Result<EagerTensor>
Forward-mode Jacobian-vector product for eager tensors.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![1], vec![3.0_f64]).unwrap(),
ctx.clone(),
)?;
let tangent = EagerTensor::from_tensor_in(
Tensor::from_vec_col_major(vec![1], vec![1.0_f64]).unwrap(),
ctx.clone(),
)?;
let y = x.mul(&x)?;
let dy = ctx.jvp(&y, &x, &tangent)?;
assert_eq!(dy.materialized()?.as_slice::<f64>().unwrap(), &[6.0]);§Errors
Returns Error::ContextMismatch for tensors from different eager
runtimes, Error::Validation when the tangent shape or dtype does not
match wrt, Error::UnsupportedAdRule when a rule is unavailable, or
a typed backend/runtime-state error.
Sourcepub fn jvp_optional(
self: &Arc<Self>,
output: &EagerTensor,
wrt: &EagerTensor,
tangent: &EagerTensor,
) -> Result<Option<EagerTensor>>
pub fn jvp_optional( self: &Arc<Self>, output: &EagerTensor, wrt: &EagerTensor, tangent: &EagerTensor, ) -> Result<Option<EagerTensor>>
Forward-mode Jacobian-vector product that returns None for inactive outputs.
§Examples
use tenferro_ad::{EagerRuntime, EagerTensor, Tensor};
use tenferro_cpu::CpuBackend;
let ctx = EagerRuntime::with_cpu_backend(CpuBackend::new())?;
let x = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![1], vec![2.0_f64]).unwrap(),
ctx.clone(),
)?;
let y = EagerTensor::requires_grad_in(
Tensor::from_vec_col_major(vec![1], vec![4.0_f64]).unwrap(),
ctx.clone(),
)?;
let tangent = EagerTensor::from_tensor_in(
Tensor::from_vec_col_major(vec![1], vec![1.0_f64]).unwrap(),
ctx.clone(),
)?;
let loss = y.mul(&y)?;
assert!(ctx.jvp_optional(&loss, &x, &tangent)?.is_none());§Errors
Returns Error::ContextMismatch for tensors from different eager
runtimes, Error::Validation when the tangent shape or dtype does not
match wrt, Error::UnsupportedAdRule when a rule is unavailable, or
a typed backend/runtime-state error.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for EagerRuntime
impl !RefUnwindSafe for EagerRuntime
impl Send for EagerRuntime
impl Sync for EagerRuntime
impl Unpin for EagerRuntime
impl UnsafeUnpin for EagerRuntime
impl !UnwindSafe for EagerRuntime
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more