From 4f572869d7894a1d51c7f08b785dcec3df08ce4e Mon Sep 17 00:00:00 2001 From: Jack Thomson Date: Fri, 11 Nov 2022 16:18:35 +0000 Subject: [PATCH] Align the cells to a cacheline size --- benches/incrementer.rs | 2 +- src/counter.rs | 15 +++++++++++---- src/lib.rs | 1 + src/utils.rs | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 src/utils.rs diff --git a/benches/incrementer.rs b/benches/incrementer.rs index c913b4c..8ac3f5b 100644 --- a/benches/incrementer.rs +++ b/benches/incrementer.rs @@ -4,7 +4,7 @@ use rayon::prelude::*; use std::sync::atomic::{AtomicIsize, Ordering}; const ITER: isize = 32 * 1024; -const CORES_TO_USE: [usize; 4] = [2, 4, 8, 16]; +const CORES_TO_USE: [usize; 5] = [1, 2, 4, 8, 16]; fn atomic_counter(c: &mut Criterion) { let mut group = c.benchmark_group("atomic_counter"); diff --git a/src/counter.rs b/src/counter.rs index a4cbab8..6e4142b 100644 --- a/src/counter.rs +++ b/src/counter.rs @@ -1,10 +1,11 @@ use std::sync::atomic::{AtomicIsize, AtomicUsize, Ordering}; use std::cell::Cell; +use crate::utils::CachePadded; use crate::safe_getters::SafeGetters; pub struct ConcurrentCounter { - cells: Vec, + cells: Vec>, } static THREAD_COUNTER: AtomicUsize = AtomicUsize::new(1); @@ -13,6 +14,12 @@ thread_local! { static THREAD_ID: Cell = Cell::new(THREAD_COUNTER.fetch_add(1, Ordering::SeqCst)); } +fn make_new_padded_counter() -> CachePadded:: { + CachePadded { + value: AtomicIsize::new(0) + } +} + impl ConcurrentCounter { #[inline] pub fn new(count: usize) -> Self { @@ -20,7 +27,7 @@ impl ConcurrentCounter { Self { cells: (0..count) .into_iter() - .map(|_| AtomicIsize::new(0)) + .map(|_| make_new_padded_counter()) .collect(), } } @@ -35,12 +42,12 @@ impl ConcurrentCounter { #[inline] pub fn add(&self, value: isize) { let c = self.cells.safely_get(self.thread_id() & (self.cells.len() - 1)); - c.fetch_add(value, Ordering::Relaxed); + c.value.fetch_add(value, Ordering::Relaxed); } #[inline] pub fn sum(&self) -> isize { - self.cells.iter().map(|c| c.load(Ordering::Relaxed)).sum() + self.cells.iter().map(|c| c.value.load(Ordering::Relaxed)).sum() } } diff --git a/src/lib.rs b/src/lib.rs index c92fd83..198a662 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #[macro_use] mod safe_getters; +mod utils; pub mod counter; pub use counter::*; diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..076c6fa --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,36 @@ +/// Pads and aligns a value to the length of a cache line. +/// Code borrowed from https://github.com/ibraheemdev/seize/blob/master/src/utils.rs +#[cfg_attr( + any( + target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "powerpc64", + ), + repr(align(128)) +)] +#[cfg_attr( + any( + target_arch = "arm", + target_arch = "mips", + target_arch = "mips64", + target_arch = "riscv64", + ), + repr(align(32)) +)] +#[cfg_attr(target_arch = "s390x", repr(align(256)))] +#[cfg_attr( + not(any( + target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "powerpc64", + target_arch = "arm", + target_arch = "mips", + target_arch = "mips64", + target_arch = "riscv64", + target_arch = "s390x", + )), + repr(align(64)) +)] +pub struct CachePadded { + pub value: T, +}