Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Test popcnt implementations
use std::time::Instant;
use std::thread::sleep;
use std::time::Duration;
macro_rules! do_timing {
($name:expr, $body:expr) => {
{
let from_time = Instant::now();
let value = {
$body
};
let duration = from_time.elapsed();
eprintln!("timing: {:>7} ms for {} result {}", duration.as_millis(), $name, value);
}
}
}
fn pause_for_thermals() {
sleep(Duration::from_secs(5));
}
#[inline(always)]
fn count_bitwise(val: u32) -> u32 {
let mut x = val;
x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
x = (x & 0x0f0f0f0f) + ((x >> 4) & 0x0f0f0f0f);
x = (x & 0x00ff00ff) + ((x >> 8) & 0x00ff00ff);
x = (x & 0x0000ffff) + (x >> 16);
x
}
#[inline(always)]
fn count_lookup(val: u32, table: &[u32]) -> u32 {
let bytes = val.to_ne_bytes();
table[bytes[0] as usize] +
table[bytes[1] as usize] +
table[bytes[2] as usize] +
table[bytes[3] as usize]
}
pub fn main() {
let mut table: Vec<u32> = Vec::with_capacity(256);
for n in (0 as u32)..256 {
table.push(n.count_ones());
}
pause_for_thermals();
do_timing!("validate ", {
let mut result: u64 = 0;
for n in 0..u32::MAX {
let truth = n.count_ones();
result += truth as u64;
assert_eq!(count_bitwise(n), truth);
assert_eq!(count_lookup(n, &table), truth);
}
result
});
pause_for_thermals();
do_timing!("count_ones ", {
let mut result: u64 = 0;
for n in 0..u32::MAX {
result += n.count_ones() as u64;
}
result
});
pause_for_thermals();
do_timing!("count_bitwise", {
let mut result: u64 = 0;
for n in 0..u32::MAX {
result += count_bitwise(n) as u64;
}
result
});
pause_for_thermals();
do_timing!("count_lookup ", {
let mut result: u64 = 0;
for n in 0..u32::MAX {
result += count_lookup(n, &table) as u64;
}
result
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment