Skip to content

Commit

Permalink
restrict Copy trait to the smallest types
Browse files Browse the repository at this point in the history
  • Loading branch information
brunocodutra committed Nov 2, 2024
1 parent 24d2a33 commit 1fef25e
Show file tree
Hide file tree
Showing 16 changed files with 93 additions and 94 deletions.
10 changes: 5 additions & 5 deletions benches/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::{str::FromStr, thread::available_parallelism};
static POSITION: Evaluator =
Evaluator::from_str("6br/1KNp1n1r/2p2p2/P1ppRP2/1kP3pP/3PBB2/PN1P4/8 w - - 0 1").unwrap();

fn bench(reps: u64, options: Options, limits: Limits) -> Duration {
fn bench(reps: u64, options: &Options, limits: &Limits) -> Duration {
let mut time = Duration::ZERO;

for _ in 0..reps {
Expand All @@ -39,22 +39,22 @@ fn crit(c: &mut Criterion) {
..Options::default()
}));

for &o in &options {
for o in &options {
let depth = Depth::new(12);
c.benchmark_group("ttd")
.sampling_mode(SamplingMode::Flat)
.bench_function(o.threads.to_string(), |b| {
b.iter_custom(|i| bench(i, o, depth.into()))
b.iter_custom(|i| bench(i, o, &depth.into()))
});
}

for &o in &options {
for o in &options {
let nodes = 300_000;
c.benchmark_group("nps")
.sampling_mode(SamplingMode::Flat)
.throughput(Throughput::Elements(nodes))
.bench_function(o.threads.to_string(), |b| {
b.iter_custom(|i| bench(i, o, nodes.into()))
b.iter_custom(|i| bench(i, o, &nodes.into()))
});
}
}
2 changes: 1 addition & 1 deletion lib/chess/board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::fmt::{self, Write};
use std::{ops::Index, str::FromStr};

/// The chess board.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(test, derive(test_strategy::Arbitrary))]
#[debug("Board({self})")]
pub struct Board {
Expand Down
18 changes: 9 additions & 9 deletions lib/chess/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ impl Moves {
/// The current position on the board board.
///
/// This type guarantees that it only holds valid positions.
#[derive(Debug, Copy, Clone, Eq)]
#[derive(Debug, Clone, Eq)]
#[debug("Position({self})")]
pub struct Position {
board: Board,
Expand All @@ -175,11 +175,11 @@ impl Default for Position {
let board = Board::default();

Self {
board,
zobrist: board.zobrist(),
checkers: Default::default(),
pinned: Default::default(),
history: Default::default(),
board,
}
}
}
Expand Down Expand Up @@ -320,7 +320,7 @@ impl Position {
match NonZeroU32::new(self.zobrist().cast()) {
None => 0,
hash => {
let history = self.history[self.turn() as usize];
let history = &self.history[self.turn() as usize];
history.iter().filter(|h| **h == hash).count()
}
}
Expand Down Expand Up @@ -664,11 +664,11 @@ impl FromStr for Position {
}

Ok(Position {
board,
checkers,
pinned,
zobrist: board.zobrist(),
history: Default::default(),
board,
})
}
}
Expand Down Expand Up @@ -779,7 +779,7 @@ mod tests {
#[filter(#pos.moves().any(|ms| ms.is_capture()))] mut pos: Position,
#[map(|s: Selector| s.select(#pos.moves().filter(MoveSet::is_capture).flatten()))] m: Move,
) {
let prev = pos;
let prev = pos.clone();
pos.play(m);
assert!(pos.material(pos.turn()).len() < prev.material(pos.turn()).len());
}
Expand All @@ -790,7 +790,7 @@ mod tests {
#[map(|s: Selector| s.select(#pos.moves().filter(MoveSet::is_promotion).flatten()))]
m: Move,
) {
let prev = pos;
let prev = pos.clone();
pos.play(m);
let pawn = Piece::new(Role::Pawn, prev.turn());
assert!(pos.board.by_piece(pawn).len() < prev.board.by_piece(pawn).len());
Expand Down Expand Up @@ -819,7 +819,7 @@ mod tests {
#[filter(#pos.outcome().is_none())] mut pos: Position,
#[map(|s: Selector| s.select(#pos.moves().flatten()))] m: Move,
) {
let prev = pos;
let prev = pos.clone();
pos.play(m);

assert_ne!(pos, prev);
Expand Down Expand Up @@ -880,14 +880,14 @@ mod tests {

#[proptest]
fn pass_updates_position(#[filter(!#pos.is_check())] mut pos: Position) {
let prev = pos;
let prev = pos.clone();
pos.pass();
assert_ne!(pos, prev);
}

#[proptest]
fn pass_reverts_itself(#[filter(!#pos.is_check() )] mut pos: Position) {
let prev = pos;
let prev = pos.clone();
pos.pass();
pos.pass();
assert_eq!(Vec::from_iter(pos.iter()), Vec::from_iter(prev.iter()));
Expand Down
2 changes: 1 addition & 1 deletion lib/nnue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub use value::*;
/// An [Efficiently Updatable Neural Network][NNUE].
///
/// [NNUE]: https://www.chessprogramming.org/NNUE
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
struct Nnue {
ft: Transformer<i16, { Positional::LEN }>,
psqt: Transformer<i32, { Material::LEN }>,
Expand Down
18 changes: 9 additions & 9 deletions lib/nnue/evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ use proptest::prelude::*;
#[derive(Debug, Display, Clone, Eq, PartialEq, Hash, Deref)]
#[debug("Evaluator({self})")]
#[display("{pos}")]
pub struct Evaluator<T: Copy + Accumulator = (Material, Positional)> {
pub struct Evaluator<T: Accumulator = (Material, Positional)> {
#[deref]
pos: Position,
acc: T,
}

#[cfg(test)]
impl<T: 'static + Copy + Accumulator> Arbitrary for Evaluator<T> {
impl<T: 'static + Accumulator> Arbitrary for Evaluator<T> {
type Parameters = ();
type Strategy = BoxedStrategy<Self>;

Expand All @@ -34,7 +34,7 @@ impl Default for Evaluator {
}
}

impl<T: Copy + Accumulator> Evaluator<T> {
impl<T: Accumulator> Evaluator<T> {
/// Constructs the evaluator from a [`Position`].
pub fn new(pos: Position) -> Self {
let mut acc = T::default();
Expand Down Expand Up @@ -146,16 +146,16 @@ impl Evaluator {
/// The [`Position`]'s material evaluator.
pub fn material(&self) -> Evaluator<Material> {
Evaluator {
pos: self.pos,
acc: self.acc.0,
pos: self.pos.clone(),
acc: self.acc.0.clone(),
}
}

/// The [`Position`]'s positional evaluator.
pub fn positional(&self) -> Evaluator<Positional> {
Evaluator {
pos: self.pos,
acc: self.acc.1,
pos: self.pos.clone(),
acc: self.acc.1.clone(),
}
}
}
Expand Down Expand Up @@ -194,15 +194,15 @@ mod tests {
#[filter(#e.outcome().is_none())] mut e: Evaluator,
#[map(|sq: Selector| sq.select(#e.moves().flatten()))] m: Move,
) {
let mut pos = e.pos;
let mut pos = e.pos.clone();
e.play(m);
pos.play(m);
assert_eq!(e, Evaluator::new(pos));
}

#[proptest]
fn pass_updates_evaluator(#[filter(!#e.is_check())] mut e: Evaluator) {
let mut pos = e.pos;
let mut pos = e.pos.clone();
e.pass();
pos.pass();
assert_eq!(e, Evaluator::new(pos));
Expand Down
26 changes: 13 additions & 13 deletions lib/nnue/hidden.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::util::AlignTo64;
use derive_more::{Constructor, Shl};

/// The hidden layer.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Constructor)]
#[derive(Debug, Clone, Eq, PartialEq, Hash, Constructor)]
#[cfg_attr(test, derive(test_strategy::Arbitrary))]
pub struct Hidden<const N: usize> {
#[cfg_attr(test, map(|b: i8| i32::from(b)))]
Expand All @@ -14,7 +14,7 @@ impl<const N: usize> Hidden<N> {
#[doc(hidden)]
#[inline(always)]
#[cfg(target_feature = "avx2")]
pub unsafe fn avx2(&self, input: [&[i16; N]; 2]) -> i32 {
pub unsafe fn avx2(&self, us: &[i16; N], them: &[i16; N]) -> i32 {
const { assert!(N % 128 == 0) };

use std::{arch::x86_64::*, mem::transmute};
Expand Down Expand Up @@ -43,7 +43,7 @@ impl<const N: usize> Hidden<N> {

let mut y = _mm256_setr_epi32(self.bias, 0, 0, 0, 0, 0, 0, 0);

for (w, i) in self.weight.iter().zip(input) {
for (w, i) in self.weight.iter().zip([us, them]) {
debug_assert_eq!(w.as_ptr() as usize % 32, 0);
debug_assert_eq!(i.as_ptr() as usize % 32, 0);

Expand Down Expand Up @@ -72,7 +72,7 @@ impl<const N: usize> Hidden<N> {
#[doc(hidden)]
#[inline(always)]
#[cfg(target_feature = "ssse3")]
pub unsafe fn sse(&self, input: [&[i16; N]; 2]) -> i32 {
pub unsafe fn sse(&self, us: &[i16; N], them: &[i16; N]) -> i32 {
const { assert!(N % 64 == 0) };

use std::{arch::x86_64::*, mem::transmute};
Expand Down Expand Up @@ -100,7 +100,7 @@ impl<const N: usize> Hidden<N> {

let mut y = _mm_setr_epi32(self.bias, 0, 0, 0);

for (w, i) in self.weight.iter().zip(input) {
for (w, i) in self.weight.iter().zip([us, them]) {
debug_assert_eq!(w.as_ptr() as usize % 16, 0);
debug_assert_eq!(i.as_ptr() as usize % 16, 0);

Expand All @@ -125,9 +125,9 @@ impl<const N: usize> Hidden<N> {

#[doc(hidden)]
#[inline(always)]
pub fn scalar(&self, input: [&[i16; N]; 2]) -> i32 {
pub fn scalar(&self, us: &[i16; N], them: &[i16; N]) -> i32 {
let mut y = self.bias;
for (w, i) in self.weight.iter().zip(input) {
for (w, i) in self.weight.iter().zip([us, them]) {
for (&a, &x) in Iterator::zip(w.iter(), i.iter()) {
y += a as i32 * (((x as i32).clamp(0, 255).shl(3i32).pow(2) + 16384) >> 15);
}
Expand All @@ -140,21 +140,21 @@ impl<const N: usize> Hidden<N> {
impl<const N: usize> Hidden<N> {
/// Transforms the accumulator.
#[inline(always)]
pub fn forward(&self, input: [&[i16; N]; 2]) -> i32 {
pub fn forward(&self, us: &[i16; N], them: &[i16; N]) -> i32 {
#[cfg(target_feature = "avx2")]
unsafe {
self.avx2(input)
self.avx2(us, them)
}

#[cfg(not(target_feature = "avx2"))]
#[cfg(target_feature = "ssse3")]
unsafe {
self.sse(input)
self.sse(us, them)
}

#[cfg(not(target_feature = "avx2"))]
#[cfg(not(target_feature = "ssse3"))]
self.scalar(input)
self.scalar(us, them)
}
}

Expand All @@ -166,12 +166,12 @@ mod tests {
#[cfg(target_feature = "avx2")]
#[proptest]
fn uses_avx(o: Hidden<128>, i: AlignTo64<[[i16; 128]; 2]>) {
assert_eq!(unsafe { o.avx2([&i[0], &i[1]]) }, o.scalar([&i[0], &i[1]]));
assert_eq!(unsafe { o.avx2(&i[0], &i[1]) }, o.scalar(&i[0], &i[1]));
}

#[cfg(target_feature = "ssse3")]
#[proptest]
fn uses_sse(o: Hidden<128>, i: AlignTo64<[[i16; 128]; 2]>) {
assert_eq!(unsafe { o.sse([&i[0], &i[1]]) }, o.scalar([&i[0], &i[1]]));
assert_eq!(unsafe { o.sse(&i[0], &i[1]) }, o.scalar(&i[0], &i[1]));
}
}
6 changes: 3 additions & 3 deletions lib/nnue/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::util::{AlignTo64, Assume};
use derive_more::Debug;

/// An accumulator for the psqt transformer.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(test, derive(test_strategy::Arbitrary))]
#[debug("Positional")]
pub struct Material(
Expand Down Expand Up @@ -64,15 +64,15 @@ mod tests {

#[proptest]
fn remove_reverses_add(a: Material, c: Color, f: Feature) {
let mut b = a;
let mut b = a.clone();
b.add(c, f);
b.remove(c, f);
assert_eq!(a, b);
}

#[proptest]
fn replace_reverses_itself(a: Material, c: Color, x: Feature, y: Feature) {
let mut b = a;
let mut b = a.clone();
b.replace(c, x, y);
b.replace(c, y, x);
assert_eq!(a, b);
Expand Down
8 changes: 4 additions & 4 deletions lib/nnue/positional.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::util::AlignTo64;
use derive_more::Debug;

/// An accumulator for the feature transformer.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(test, derive(test_strategy::Arbitrary))]
#[debug("Positional")]
pub struct Positional(
Expand Down Expand Up @@ -44,7 +44,7 @@ impl Accumulator for Positional {

#[inline(always)]
fn evaluate(&self, turn: Color, phase: usize) -> i32 {
Nnue::hidden(phase).forward([&self.0[turn as usize], &self.0[turn.flip() as usize]]) / 40
Nnue::hidden(phase).forward(&self.0[turn as usize], &self.0[turn.flip() as usize]) / 40
}
}

Expand All @@ -57,15 +57,15 @@ mod tests {

#[proptest]
fn remove_reverses_add(a: Positional, c: Color, f: Feature) {
let mut b = a;
let mut b = a.clone();
b.add(c, f);
b.remove(c, f);
assert_eq!(a, b);
}

#[proptest]
fn replace_reverses_itself(a: Positional, c: Color, x: Feature, y: Feature) {
let mut b = a;
let mut b = a.clone();
b.replace(c, x, y);
b.replace(c, y, x);
assert_eq!(a, b);
Expand Down
2 changes: 1 addition & 1 deletion lib/nnue/transformer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use proptest::{prelude::*, sample::Index};
use std::ops::Range;

/// A feature transformer.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Constructor)]
#[derive(Debug, Clone, Eq, PartialEq, Hash, Constructor)]
pub struct Transformer<T, const N: usize> {
pub(super) bias: AlignTo64<[T; N]>,
pub(super) weight: AlignTo64<[[T; N]; Feature::LEN]>,
Expand Down
4 changes: 2 additions & 2 deletions lib/search/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use rayon::{prelude::*, ThreadPool, ThreadPoolBuilder};
use std::sync::atomic::{AtomicU64, Ordering};

/// Whether the search should be [`Interrupted`] or exited early.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, From)]
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, From)]
pub enum ControlFlow {
Interrupt(Interrupted),
Break,
Expand Down Expand Up @@ -68,7 +68,7 @@ impl Driver {
}
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deref)]
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Deref)]
#[cfg_attr(test, derive(test_strategy::Arbitrary))]
struct IndexedPv(#[deref] Pv, u32);

Expand Down
Loading

0 comments on commit 1fef25e

Please sign in to comment.