Skip to content

Commit

Permalink
sort: guarantee rather than assume cache aligned allocations
Browse files Browse the repository at this point in the history
  • Loading branch information
benesch committed Apr 4, 2019
1 parent 387631f commit f98a286
Showing 1 changed file with 21 additions and 7 deletions.
28 changes: 21 additions & 7 deletions sort/src/swc_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,45 @@ macro_rules! per_cache_line {
($t:ty) => {{ ::std::cmp::max(64 / ::std::mem::size_of::<$t>(), 4) }}
}

#[repr(align(64))]
pub struct CacheLine([u8; 64]);

pub struct SWCBuffer<T> {
staged: Vec<T>,
counts: [u8; 256],
staged: Vec<CacheLine>,
phantom: std::marker::PhantomData<T>,
}

impl<T> SWCBuffer<T> {

pub fn new() -> Self {
let staged = Vec::with_capacity(256 * per_cache_line!(T));
let addr: usize = unsafe { ::std::mem::transmute(staged.as_ptr()) };
let nlines = (256 * per_cache_line!(T) * std::mem::size_of::<T>()) / 64;
let staged = Vec::<CacheLine>::with_capacity(nlines);

// looks like this is often cache-line aligned; yay!
// verify cache alignment
let addr = staged.as_ptr() as usize;
assert_eq!(addr % 64, 0);

SWCBuffer {
staged: staged,
counts: [0u8; 256],
phantom: std::marker::PhantomData,
}
}

fn staged_ptr(&self) -> *const T {
self.staged.as_ptr() as _
}

fn staged_mut_ptr(&mut self) -> *mut T {
self.staged.as_mut_ptr() as _
}

#[inline]
pub fn slice(&self, byte: usize) -> &[T] {
unsafe {
slice::from_raw_parts(
self.staged.as_ptr().offset(per_cache_line!(T) as isize * byte as isize),
self.staged_ptr().offset(per_cache_line!(T) as isize * byte as isize),
*self.counts.get_unchecked(byte) as usize
)
}
Expand All @@ -51,7 +65,7 @@ impl<T> SWCBuffer<T> {
pub fn push(&mut self, element: T, byte: usize) {
unsafe {
let offset = per_cache_line!(T) as isize * byte as isize + *self.counts.get_unchecked(byte as usize) as isize;
::std::ptr::write(self.staged.as_mut_ptr().offset(offset), element);
::std::ptr::write(self.staged_mut_ptr().offset(offset), element);
*self.counts.get_unchecked_mut(byte) += 1;
}
}
Expand All @@ -70,7 +84,7 @@ impl<T> SWCBuffer<T> {
pub fn drain_into_vec(&mut self, byte: usize, batch: &mut Vec<T>, _stash: &mut Stash<T>) {
unsafe {
for i in 0 .. *self.counts.get_unchecked(byte) {
batch.push(::std::ptr::read(self.staged.as_mut_ptr().offset(per_cache_line!(T) as isize * byte as isize + i as isize)));
batch.push(::std::ptr::read(self.staged_mut_ptr().offset(per_cache_line!(T) as isize * byte as isize + i as isize)));
}
*self.counts.get_unchecked_mut(byte) = 0;
}
Expand Down

0 comments on commit f98a286

Please sign in to comment.