mod cpu;
pub use cpu::CpuBackend;
use crate::data::BinnedDataset;
use crate::error::Result;
use crate::quantize::QuantSpec;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct LeafRange {
pub begin: u32,
pub count: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct BinSplit {
pub group: u32,
pub column: u32,
pub left_bins: [u32; 8],
}
impl BinSplit {
#[inline]
pub fn goes_left(&self, bin: u8) -> bool {
(self.left_bins[usize::from(bin) / 32] >> (bin % 32)) & 1 == 1
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DeviceNode {
pub split: BinSplit,
pub left: i32,
pub right: i32,
}
#[derive(Debug, Clone, PartialEq)]
pub struct DeviceTree {
pub nodes: Vec<DeviceNode>,
pub leaf_values: Vec<f32>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum ObjectiveSetup {
Regression,
Binary {
sigmoid: f64,
},
LambdaRank {
sigmoid: f64,
norm: bool,
truncation_level: u32,
label_gain: Vec<f64>,
inverse_max_dcg: Vec<f64>,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct GradientStats {
pub max_abs_grad: f64,
pub max_hess: f64,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BagSpec {
All,
Bernoulli {
seed: u32,
round: u32,
fraction: f64,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Side {
Left,
Right,
}
impl Side {
pub fn range(self, leaf: LeafRange, left: u32) -> LeafRange {
match self {
Side::Left => LeafRange {
begin: leaf.begin,
count: left,
},
Side::Right => LeafRange {
begin: leaf.begin + left,
count: leaf.count - left,
},
}
}
}
pub trait Backend {
fn name(&self) -> String;
fn set_thread_pool(&mut self, pool: std::sync::Arc<rayon::ThreadPool>) {
let _ = pool;
}
fn load(&mut self, train: &BinnedDataset, valid: &[&BinnedDataset], objective: &ObjectiveSetup) -> Result<()>;
fn init_scores(&mut self, dataset: usize, value: f64) -> Result<()>;
fn compute_gradients(&mut self) -> Result<GradientStats>;
fn quantize(&mut self, spec: &QuantSpec) -> Result<()>;
fn reset_partition(&mut self, bag: &BagSpec) -> Result<u32>;
fn set_histogram_features(&mut self, used: &[bool]) {
let _ = used;
}
fn histogram(&mut self, leaf: LeafRange, quantized: bool, out: &mut [f64]) -> Result<()>;
fn partition(&mut self, leaf: LeafRange, split: &BinSplit) -> Result<u32>;
fn partition_and_histogram(
&mut self,
leaf: LeafRange,
split: &BinSplit,
side: Side,
quantized: bool,
out: &mut [f64],
) -> Result<u32> {
let left = self.partition(leaf, split)?;
self.histogram(side.range(leaf, left), quantized, out)?;
Ok(left)
}
fn leaf_sums(&mut self, leaves: &[LeafRange], grad_scale: f32, hess_scale: f32) -> Result<Vec<[i64; 2]>>;
fn add_tree(&mut self, tree: &DeviceTree) -> Result<()>;
fn scores(&mut self, dataset: usize) -> Result<Vec<f32>>;
}