diff --git a/src/networks/accumulator.rs b/src/networks/accumulator.rs index 775aab26..dd5c7cab 100644 --- a/src/networks/accumulator.rs +++ b/src/networks/accumulator.rs @@ -20,6 +20,35 @@ impl + Copy + Mul, const N: usize> Accumulator Accumulator { + pub fn add_multi(&mut self, adds: &[usize], weights: &[Self]) { + const REGS: usize = 8; + const PER: usize = REGS * 16; + + let mut regs = [0i16; PER]; + + for i in 0..N / PER { + let offset = PER * i; + + for (j, reg) in regs.iter_mut().enumerate() { + *reg = self.0[offset + j]; + } + + for &add in adds { + let this_weight = &weights[usize::from(add)]; + + for (j, reg) in regs.iter_mut().enumerate() { + *reg += this_weight.0[offset + j]; + } + } + + for (j, reg) in regs.iter().enumerate() { + self.0[offset + j] = *reg; + } + } + } +} + impl Accumulator { pub fn dot(&self, other: &Self) -> f32 { let mut res = 0.0; diff --git a/src/networks/layer.rs b/src/networks/layer.rs index 8a470d20..d742a658 100644 --- a/src/networks/layer.rs +++ b/src/networks/layer.rs @@ -10,9 +10,16 @@ pub struct Layer { impl Layer { pub fn forward(&self, board: &Board) -> Accumulator { + let mut count = 0; + let mut feats = [0; 32]; + board.map_value_features(|feat| { + feats[count] = feat; + count += 1; + }); + let mut out = self.biases; - board.map_value_features(|feat| out.add(&self.weights[feat])); + out.add_multi(&feats[..count], &self.weights); out }