#[cfg(feature = "nnue-stats")]
use std::sync::atomic::{AtomicU64, Ordering};
#[cfg(feature = "nnue-stats")]
pub struct NnueStats {
pub refresh_count: AtomicU64,
pub update_count: AtomicU64,
pub forward_update_count: AtomicU64,
pub evaluate_count: AtomicU64,
pub already_computed_count: AtomicU64,
}
#[cfg(feature = "nnue-stats")]
impl NnueStats {
pub const fn new() -> Self {
Self {
refresh_count: AtomicU64::new(0),
update_count: AtomicU64::new(0),
forward_update_count: AtomicU64::new(0),
evaluate_count: AtomicU64::new(0),
already_computed_count: AtomicU64::new(0),
}
}
pub fn reset(&self) {
self.refresh_count.store(0, Ordering::Relaxed);
self.update_count.store(0, Ordering::Relaxed);
self.forward_update_count.store(0, Ordering::Relaxed);
self.evaluate_count.store(0, Ordering::Relaxed);
self.already_computed_count.store(0, Ordering::Relaxed);
}
#[inline]
pub fn count_refresh(&self) {
self.refresh_count.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn count_update(&self) {
self.update_count.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn count_forward_update(&self) {
self.forward_update_count.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn count_evaluate(&self) {
self.evaluate_count.fetch_add(1, Ordering::Relaxed);
}
#[inline]
pub fn count_already_computed(&self) {
self.already_computed_count.fetch_add(1, Ordering::Relaxed);
}
pub fn snapshot(&self) -> NnueStatsSnapshot {
NnueStatsSnapshot {
refresh_count: self.refresh_count.load(Ordering::Relaxed),
update_count: self.update_count.load(Ordering::Relaxed),
forward_update_count: self.forward_update_count.load(Ordering::Relaxed),
evaluate_count: self.evaluate_count.load(Ordering::Relaxed),
already_computed_count: self.already_computed_count.load(Ordering::Relaxed),
}
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct NnueStatsSnapshot {
pub refresh_count: u64,
pub update_count: u64,
pub forward_update_count: u64,
pub evaluate_count: u64,
pub already_computed_count: u64,
}
impl NnueStatsSnapshot {
pub fn total_accumulator_updates(&self) -> u64 {
self.refresh_count + self.update_count + self.forward_update_count
}
pub fn refresh_rate(&self) -> f64 {
let total = self.total_accumulator_updates();
if total == 0 {
0.0
} else {
self.refresh_count as f64 / total as f64 * 100.0
}
}
pub fn update_rate(&self) -> f64 {
let total = self.total_accumulator_updates();
if total == 0 {
0.0
} else {
self.update_count as f64 / total as f64 * 100.0
}
}
pub fn forward_update_rate(&self) -> f64 {
let total = self.total_accumulator_updates();
if total == 0 {
0.0
} else {
self.forward_update_count as f64 / total as f64 * 100.0
}
}
pub fn incremental_rate(&self) -> f64 {
100.0 - self.refresh_rate()
}
pub fn print_report(&self) {
let total = self.total_accumulator_updates();
eprintln!("=== NNUE Accumulator Stats ===");
eprintln!("evaluate calls: {:>12}", self.evaluate_count);
eprintln!("already computed: {:>12}", self.already_computed_count);
eprintln!("accumulator updates: {:>12}", total);
eprintln!(
" refresh: {:>12} ({:>5.1}%)",
self.refresh_count,
self.refresh_rate()
);
eprintln!(
" update (1-step): {:>12} ({:>5.1}%)",
self.update_count,
self.update_rate()
);
eprintln!(
" forward_update: {:>12} ({:>5.1}%)",
self.forward_update_count,
self.forward_update_rate()
);
eprintln!("incremental rate: {:>11.1}%", self.incremental_rate());
eprintln!("==============================");
}
}
#[cfg(feature = "nnue-stats")]
pub static NNUE_STATS: NnueStats = NnueStats::new();
#[cfg(feature = "nnue-stats")]
pub fn reset_nnue_stats() {
NNUE_STATS.reset();
}
#[cfg(feature = "nnue-stats")]
pub fn get_nnue_stats() -> NnueStatsSnapshot {
NNUE_STATS.snapshot()
}
#[cfg(feature = "nnue-stats")]
pub fn print_nnue_stats() {
NNUE_STATS.snapshot().print_report();
}
#[cfg(not(feature = "nnue-stats"))]
#[inline]
pub fn reset_nnue_stats() {}
#[cfg(not(feature = "nnue-stats"))]
#[inline]
pub fn get_nnue_stats() -> NnueStatsSnapshot {
NnueStatsSnapshot::default()
}
#[cfg(not(feature = "nnue-stats"))]
#[inline]
pub fn print_nnue_stats() {}
#[cfg(feature = "nnue-stats")]
macro_rules! count_refresh {
() => {
$crate::nnue::stats::NNUE_STATS.count_refresh()
};
}
#[cfg(not(feature = "nnue-stats"))]
macro_rules! count_refresh {
() => {};
}
#[cfg(feature = "nnue-stats")]
macro_rules! count_update {
() => {
$crate::nnue::stats::NNUE_STATS.count_update()
};
}
#[cfg(not(feature = "nnue-stats"))]
macro_rules! count_update {
() => {};
}
#[cfg(feature = "nnue-stats")]
macro_rules! count_already_computed {
() => {
$crate::nnue::stats::NNUE_STATS.count_already_computed()
};
}
#[cfg(not(feature = "nnue-stats"))]
macro_rules! count_already_computed {
() => {};
}
pub(crate) use count_already_computed;
pub(crate) use count_refresh;
pub(crate) use count_update;