pub mod buffers;
pub mod context;
pub mod dense;
pub use context::is_available;
pub use dense::GpuDenseLayer;
use pyo3::prelude::*;
#[pyclass(
name = "GpuDenseLayer",
module = "sc_neurocore_engine.sc_neurocore_engine"
)]
pub struct PyGpuDenseLayer {
inner: GpuDenseLayer,
}
#[pymethods]
impl PyGpuDenseLayer {
#[new]
#[pyo3(signature = (n_inputs, n_neurons, length=1024, seed=24301, max_batch=256))]
fn new(
n_inputs: usize,
n_neurons: usize,
length: usize,
seed: u64,
max_batch: usize,
) -> PyResult<Self> {
let inner = GpuDenseLayer::try_new(n_inputs, n_neurons, length, seed, max_batch)
.ok_or_else(|| {
pyo3::exceptions::PyRuntimeError::new_err(
"No GPU available. Check Vulkan/Metal drivers.",
)
})?;
Ok(PyGpuDenseLayer { inner })
}
#[pyo3(signature = (input_values, seed=42))]
fn forward_fast(&self, input_values: Vec<f64>, seed: u64) -> PyResult<Vec<f64>> {
Ok(self.inner.forward_gpu(&input_values, seed))
}
#[pyo3(signature = (inputs_flat, n_samples, seed=42))]
fn forward_batch(
&self,
inputs_flat: Vec<f64>,
n_samples: usize,
seed: u64,
) -> PyResult<Vec<f64>> {
Ok(self.inner.forward_batch_gpu(&inputs_flat, n_samples, seed))
}
fn gpu_name(&self) -> String {
self.inner.gpu_name().to_string()
}
#[staticmethod]
fn is_gpu_available() -> bool {
is_available()
}
#[getter]
fn n_inputs(&self) -> usize {
self.inner.cpu.n_inputs
}
#[getter]
fn n_neurons(&self) -> usize {
self.inner.cpu.n_neurons
}
#[getter]
fn length(&self) -> usize {
self.inner.cpu.length
}
}