use cudarc::driver::CudaSlice;
use super::dispatch::LSTM;
use super::shape::WINDOW_SAMPLES;
use super::{CudaSegmentation, LstmStage, SegmentationShape, SegmentationWorkspace};
use crate::inference::cuda::implementation::Choice;
use crate::inference::cuda::{CudaError, CudaRuntime, DeviceTensor};
impl CudaSegmentation {
pub(crate) fn select_lstm(
&mut self,
runtime: &CudaRuntime,
shape: [usize; 2],
choice: Choice,
) -> Result<(), CudaError> {
let index = self.workspace_index(runtime, shape[0], shape[1])?;
let shape = self.workspaces[index].shape;
let selected = crate::inference::cuda::implementation::plan_selection(
runtime,
LSTM,
shape.batch,
self.network.options.math,
Some(choice),
)?;
let plan = self.network.plan_lstm(runtime, shape, selected)?;
let workspace = &mut self.workspaces[index];
workspace.lstm = plan;
workspace.graph = None;
Ok(())
}
pub(crate) fn run_lstm(
&mut self,
runtime: &CudaRuntime,
batch: usize,
input: &CudaSlice<f32>,
output: &mut CudaSlice<f32>,
) -> Result<(), CudaError> {
let index = self.workspace_index(runtime, batch, WINDOW_SAMPLES)?;
self.network
.lstm_forward(runtime, &mut self.workspaces[index].lstm, input, output)
}
pub fn sinc_filters(&self) -> &CudaSlice<f32> {
&self.network.sinc_filters
}
pub fn find_workspace(&self, batch: usize, samples: usize) -> Option<&SegmentationWorkspace> {
self.workspaces
.iter()
.find(|workspace| workspace.matches(batch, samples))
}
pub fn forward(
&mut self,
runtime: &CudaRuntime,
batch: usize,
samples: usize,
) -> Result<(), CudaError> {
let index = self.workspace_index(runtime, batch, samples)?;
self.network.forward(runtime, &mut self.workspaces[index])
}
}
impl SegmentationWorkspace {
pub fn shape(&self) -> SegmentationShape {
self.shape
}
pub fn tensor(&self, tensor: SegmentationTensor) -> &DeviceTensor {
let t = &self.tensors;
match tensor {
SegmentationTensor::Input => &t.input,
SegmentationTensor::WaveNorm => &t.wave_norm,
SegmentationTensor::SincConv => &t.sinc,
SegmentationTensor::Stage0 => &t.stage0,
SegmentationTensor::Conv1 => &t.conv1,
SegmentationTensor::Stage1 => &t.stage1,
SegmentationTensor::Conv2 => &t.conv2,
SegmentationTensor::LstmInput => &t.lstm_input,
SegmentationTensor::LstmOutput => &t.lstm_output,
SegmentationTensor::Linear0 => &t.linear0,
SegmentationTensor::Linear1 => &t.linear1,
SegmentationTensor::Output => &t.output,
}
}
pub fn activation_bytes(&self) -> usize {
SegmentationTensor::ALL
.into_iter()
.map(|tensor| self.tensor(tensor).len() * size_of::<f32>())
.sum()
}
pub fn lstm_workspace_bytes(&self) -> usize {
match &self.lstm {
LstmStage::Library(plan) => plan.workspace_bytes(),
LstmStage::Oxide { .. } | LstmStage::Projected { .. } => 0,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SegmentationTensor {
Input,
WaveNorm,
SincConv,
Stage0,
Conv1,
Stage1,
Conv2,
LstmInput,
LstmOutput,
Linear0,
Linear1,
Output,
}
impl SegmentationTensor {
pub const ALL: [Self; 12] = [
Self::Input,
Self::WaveNorm,
Self::SincConv,
Self::Stage0,
Self::Conv1,
Self::Stage1,
Self::Conv2,
Self::LstmInput,
Self::LstmOutput,
Self::Linear0,
Self::Linear1,
Self::Output,
];
}
impl CudaSegmentation {
pub const WINDOW_SAMPLES: usize = WINDOW_SAMPLES;
}