use alloc::{sync::Arc, vec::Vec};
#[cfg(feature = "distributed")]
use burn_backend::distributed::DistributedParams;
#[cfg(target_has_atomic = "64")]
use core::sync::atomic::{AtomicU64, Ordering};
#[cfg(not(target_has_atomic = "64"))]
use portable_atomic::{AtomicU64, Ordering};
use crate::checkpoint::retro_forward::RetroForward;
use crate::runtime::AutodiffClientImpl;
use super::Requirement;
#[derive(Debug, Clone)]
pub enum ComputingProperty {
ComputeBound,
MemoryBound {
retro_forward: Arc<dyn RetroForward>,
},
Ambiguous, }
unsafe impl Send for ComputingProperty {}
unsafe impl Sync for ComputingProperty {}
#[derive(new, Debug)]
pub struct Node {
pub parents: Vec<Parent>,
pub order: usize,
pub id: NodeId,
pub requirement: Requirement,
pub properties: ComputingProperty,
pub client: AutodiffClientImpl,
#[cfg(feature = "distributed")]
pub distributed_params: Option<DistributedParams>,
}
pub type NodeRef = Arc<Node>;
#[derive(new, Debug, Clone, PartialEq, Eq)]
pub struct Parent {
pub id: NodeId,
}
impl Node {
pub fn clone_if_require_grad(self: &Arc<Self>) -> Option<NodeRef> {
match self.requirement.is_none() {
true => None,
false => Some(self.clone()),
}
}
}
#[derive(Clone, Hash, PartialEq, Eq, Debug, Copy)]
pub struct NodeId {
pub value: u64,
}
impl core::fmt::Display for NodeId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_fmt(format_args!("NodeId({})", self.value))
}
}
impl NodeId {
pub fn new() -> Self {
static COUNTER: AtomicU64 = AtomicU64::new(0);
let value = COUNTER.fetch_add(1, Ordering::Relaxed);
if value == u64::MAX {
panic!("NodeId overflowed");
}
Self { value }
}
}
impl Default for NodeId {
fn default() -> Self {
Self::new()
}
}