Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 2 additions & 18 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,2 @@
[target.x86_64-unknown-linux-gnu]
rustflags = [
"-C", "target-cpu=native",
"-C", "target-feature=+fp16"
]

[target.aarch64-apple-darwin]
[build]
rustflags = [
"-C", "target-cpu=native",
"-C", "target-feature=+fp16"
]

[target.wasm32-unknown-unknown]
rustflags = ["-C", "target-feature=+simd128"]

[target.x86_64-apple-darwin]
rustflags = ["-C", "target-feature=-avx,-avx2"]
[build]
incremental = false
118 changes: 112 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ cudarc = { version = "0.16.1", features = ["std", "cublas", "cublaslt", "curand"
thiserror = "1.0.61"
half = "2.4.1"
petgraph = "0.8.1"
dirs = "5.0.1"
rayon = "1.10.0"
gemm = "0.18"
num_cpus = "1.16.0"
rand = "0.9.1"
rand_distr = "0.5.1"
10 changes: 6 additions & 4 deletions constensor-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ readme = "README.md"
cudarc = { workspace = true, optional = true }
thiserror.workspace = true
half = { workspace = true, optional = true }
dirs = "5.0.1"
rayon = "1.10.0"
dirs.workspace = true
rayon.workspace = true
petgraph.workspace = true
gemm = "0.18"
num_cpus = "1.16.0"
gemm.workspace = true
num_cpus.workspace = true
rand.workspace = true
rand_distr.workspace = true

[features]
default = ["half", "bfloat"]
Expand Down
26 changes: 24 additions & 2 deletions constensor-core/src/cpu_storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ use crate::{
storage::{BackendDevice, BackendStorage},
CompiledGraph, DType, GraphNode, Op, Result,
};
use rand::rng;
use rand::Rng;
use rand_distr::{Distribution, Normal};

mod pool;

Expand Down Expand Up @@ -59,8 +62,8 @@ impl BackendDevice for CpuDevice {
dep_graph.add_edge(l_id.get(), idx, ());
dep_graph.add_edge(r_id.get(), idx, ());
}
// NoOp and Fill/Arange don’t create incoming edges
Op::NoOp | Op::Fill { .. } | Op::Arange { .. } => {}
// NoOp, Fill/Arange, Rand/Randn don’t create incoming edges
Op::NoOp | Op::Fill { .. } | Op::Arange { .. } | Op::Rand | Op::Randn { .. } => {}
}
}

Expand Down Expand Up @@ -96,6 +99,8 @@ impl BackendDevice for CpuDevice {
let mut results: Vec<Option<PooledBuffer<T>>> = Vec::with_capacity(graph.len());
results.resize_with(graph.len(), || None);

let mut rng = rng();

// Evaluate nodes in topological order
for idx in order.clone() {
let op = &graph[idx];
Expand Down Expand Up @@ -141,6 +146,23 @@ impl BackendDevice for CpuDevice {
}
PooledBuffer::new(buf, pool.clone())
}
Op::Rand => {
let mut buf = pool.borrow_mut().get_buffer(out_elem_count);
for elt in &mut buf {
*elt = T::from_f64(rng.random());
}
PooledBuffer::new(buf, pool.clone())
}
Op::Randn { mean, std } => {
let mean_f = mean.to_f64();
let std_f = std.to_f64();
let normal = Normal::new(mean_f, std_f).unwrap();
let mut buf = pool.borrow_mut().get_buffer(out_elem_count);
for elt in &mut buf {
*elt = T::from_f64(normal.sample(&mut rng));
}
PooledBuffer::new(buf, pool.clone())
}
Op::UnaryOp { v_id, operator } => {
let buf = results[v_id.get()].as_ref().unwrap();
let op_fn = operator.to_closure();
Expand Down
20 changes: 17 additions & 3 deletions constensor-core/src/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ impl<T: DType> Graph<T> {
} => {
format!("Arange(start={start:?}, step={step:?}, stop={stop:?})")
}
Op::Rand => "Rand".to_string(),
Op::Randn { mean, std } => {
format!("Randn(mean={mean:?}, std={std:?})")
}
Op::BinaryOp { operator, .. } => format!("BinOp({})", operator.as_c_op()),
Op::UnaryOp { operator, .. } => format!("UnOp({operator:?})"),
Op::FusedMulAdd { .. } => "FMA".to_string(),
Expand Down Expand Up @@ -166,8 +170,8 @@ impl<T: DType> Graph<T> {
}
}
}
// NoOp and Fill/Arange don’t create incoming edges
Op::NoOp | Op::Fill { .. } | Op::Arange { .. } => {}
// NoOp, Fill/Arange, Rand/Randn don’t create incoming edges
Op::NoOp | Op::Fill { .. } | Op::Arange { .. } | Op::Rand | Op::Randn { .. } => {}
}
}

Expand Down Expand Up @@ -297,6 +301,8 @@ impl<T: DType> Graph<T> {
stop: _,
..
} => vec![],
Op::Rand => vec![],
Op::Randn { mean: _, std: _ } => vec![],
Op::BinaryOp { l_id, r_id, .. } => vec![l_id, r_id],
Op::Fill { v: _, .. } => vec![],
Op::UnaryOp {
Expand Down Expand Up @@ -361,7 +367,8 @@ impl<T: DType> Graph<T> {
*usage.entry(l_id.clone()).or_default() += 1;
*usage.entry(r_id.clone()).or_default() += 1;
}
Op::NoOp | Op::Fill { .. } | Op::Arange { .. } => {}
// No input usage for these ops
Op::NoOp | Op::Fill { .. } | Op::Arange { .. } | Op::Rand | Op::Randn { .. } => {}
}
}
usage
Expand Down Expand Up @@ -721,6 +728,13 @@ pub enum Op<T: DType> {
alpha: T,
beta: T,
},
/// Fill with uniform random values in [0, 1).
Rand,
/// Fill with normally distributed random values (mean, std).
Randn {
mean: T,
std: T,
},
NoOp,
}

Expand Down
29 changes: 28 additions & 1 deletion constensor-core/src/tensor/graphtensor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
};

use crate::{
device::Dev,
device::{Cpu, Dev},
graph::{BinaryOpType, Graph, GraphTensorId, Op, UnaryOpType},
DType, Shape, R1, R3,
};
Expand Down Expand Up @@ -146,6 +146,33 @@ impl<const A: usize, T: DType, D: Dev> GraphTensor<R1<A>, T, D> {
}
}

// CPU-only random initializations
impl<S: Shape, T: DType> GraphTensor<S, T, Cpu> {
#[must_use]
/// Create a tensor filled with uniform random values in [0,1).
pub fn rand(graph: &mut Graph<T>) -> Self {
let id = graph.next_id();
graph.add_op::<S>(Op::Rand);
GraphTensor {
id,
graph: Arc::new(RwLock::new(graph.clone())),
_ghost: PhantomData,
}
}

#[must_use]
/// Create a tensor filled with normally distributed random values (mean, std).
pub fn randn(graph: &mut Graph<T>, mean: T, std: T) -> Self {
let id = graph.next_id();
graph.add_op::<S>(Op::Randn { mean, std });
GraphTensor {
id,
graph: Arc::new(RwLock::new(graph.clone())),
_ghost: PhantomData,
}
}
}

macro_rules! graphtensor_binop {
($trait:ident, $fn_name:ident) => {
impl<S: Shape, T: DType, D: Dev> $trait for GraphTensor<S, T, D> {
Expand Down
Loading
Loading