Make calibration able to autodetect micro architecture - still hacky for number of cores
This commit is contained in:
parent
80c6a556bf
commit
c84aefa2e8
@ -1,11 +1,21 @@
|
|||||||
#![allow(clippy::missing_safety_doc)]
|
#![allow(clippy::missing_safety_doc)]
|
||||||
|
|
||||||
|
use crate::complex_addressing::{cache_slicing, CacheSlicing};
|
||||||
use crate::{flush, maccess, rdtsc_fence};
|
use crate::{flush, maccess, rdtsc_fence};
|
||||||
|
|
||||||
|
use cpuid::MicroArchitecture;
|
||||||
|
|
||||||
use core::arch::x86_64 as arch_x86;
|
use core::arch::x86_64 as arch_x86;
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use polling_serial::{serial_print as print, serial_println as println};
|
use polling_serial::{serial_print as print, serial_println as println};
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
use crate::calibration::Verbosity::*;
|
||||||
|
use alloc::vec;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
use core::cmp::min;
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
#[derive(Ord, PartialOrd, Eq, PartialEq)]
|
#[derive(Ord, PartialOrd, Eq, PartialEq)]
|
||||||
pub enum Verbosity {
|
pub enum Verbosity {
|
||||||
NoOutput,
|
NoOutput,
|
||||||
@ -20,14 +30,6 @@ pub struct HistParams {
|
|||||||
bucket_number: usize,
|
bucket_number: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
extern crate alloc;
|
|
||||||
use crate::calibration::Verbosity::*;
|
|
||||||
use crate::complex_addressing::AddressHasher;
|
|
||||||
use alloc::vec;
|
|
||||||
use alloc::vec::Vec;
|
|
||||||
use core::cmp::min;
|
|
||||||
use itertools::Itertools;
|
|
||||||
|
|
||||||
pub unsafe fn only_reload(p: *const u8) -> u64 {
|
pub unsafe fn only_reload(p: *const u8) -> u64 {
|
||||||
let t = rdtsc_fence();
|
let t = rdtsc_fence();
|
||||||
maccess(p);
|
maccess(p);
|
||||||
@ -194,7 +196,6 @@ pub fn calibrate_flush(
|
|||||||
iterations: CFLUSH_NUM_ITER,
|
iterations: CFLUSH_NUM_ITER,
|
||||||
},
|
},
|
||||||
verbose_level,
|
verbose_level,
|
||||||
None,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +235,6 @@ pub unsafe fn calibrate(
|
|||||||
iterations: num_iterations,
|
iterations: num_iterations,
|
||||||
},
|
},
|
||||||
verbosity_level,
|
verbosity_level,
|
||||||
None,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,18 +246,7 @@ fn calibrate_impl_fixed_freq(
|
|||||||
operations: &[CalibrateOperation],
|
operations: &[CalibrateOperation],
|
||||||
hist_params: HistParams,
|
hist_params: HistParams,
|
||||||
verbosity_level: Verbosity,
|
verbosity_level: Verbosity,
|
||||||
hasher: Option<&AddressHasher>,
|
|
||||||
) -> Vec<CalibrateResult> {
|
) -> Vec<CalibrateResult> {
|
||||||
// TODO : adapt this to detect CPU generation and grab the correct masks.
|
|
||||||
// These are the skylake masks.
|
|
||||||
/*let masks: [usize; 3] = [
|
|
||||||
0b1111_0011_0011_0011_0010_0100_1100_0100_000000,
|
|
||||||
0b1011_1010_1101_0111_1110_1010_1010_0010_000000,
|
|
||||||
0b0110_1101_0111_1101_0101_1101_0101_0001_000000,
|
|
||||||
];
|
|
||||||
|
|
||||||
let hasher = AddressHasher::new(&masks);
|
|
||||||
*/
|
|
||||||
if verbosity_level >= Thresholds {
|
if verbosity_level >= Thresholds {
|
||||||
println!(
|
println!(
|
||||||
"Calibrating {}...",
|
"Calibrating {}...",
|
||||||
@ -270,10 +259,28 @@ fn calibrate_impl_fixed_freq(
|
|||||||
|
|
||||||
let to_bucket = |time: u64| -> usize { time as usize / hist_params.bucket_size };
|
let to_bucket = |time: u64| -> usize { time as usize / hist_params.bucket_size };
|
||||||
let from_bucket = |bucket: usize| -> u64 { (bucket * hist_params.bucket_size) as u64 };
|
let from_bucket = |bucket: usize| -> u64 { (bucket * hist_params.bucket_size) as u64 };
|
||||||
|
|
||||||
|
let slicing = if let Some(uarch) = MicroArchitecture::get_micro_architecture() {
|
||||||
|
Some(cache_slicing(uarch, 8))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let h = if let Some(s) = slicing {
|
||||||
|
if s.can_hash() {
|
||||||
|
Some(|addr: usize| -> usize { slicing.unwrap().hash(addr).unwrap() })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
// TODO fix the GROSS hack of using max cpu core supported
|
||||||
|
|
||||||
let mut ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
if verbosity_level >= Thresholds {
|
if verbosity_level >= Thresholds {
|
||||||
print!("CSV: address, ");
|
print!("CSV: address, ");
|
||||||
if hasher.is_some() {
|
if h.is_some() {
|
||||||
print!("hash, ");
|
print!("hash, ");
|
||||||
}
|
}
|
||||||
println!(
|
println!(
|
||||||
@ -294,7 +301,7 @@ fn calibrate_impl_fixed_freq(
|
|||||||
}
|
}
|
||||||
if verbosity_level >= RawResult {
|
if verbosity_level >= RawResult {
|
||||||
print!("RESULT:address,");
|
print!("RESULT:address,");
|
||||||
if hasher.is_some() {
|
if h.is_some() {
|
||||||
print!("hash,");
|
print!("hash,");
|
||||||
}
|
}
|
||||||
println!(
|
println!(
|
||||||
@ -308,7 +315,7 @@ fn calibrate_impl_fixed_freq(
|
|||||||
|
|
||||||
for i in (0..len).step_by(increment) {
|
for i in (0..len).step_by(increment) {
|
||||||
let pointer = unsafe { p.offset(i) };
|
let pointer = unsafe { p.offset(i) };
|
||||||
let hash = hasher.map(|h| h.hash(pointer as usize));
|
let hash = h.map(|h| h(pointer as usize));
|
||||||
|
|
||||||
if verbosity_level >= Thresholds {
|
if verbosity_level >= Thresholds {
|
||||||
print!("Calibration for {:p}", pointer);
|
print!("Calibration for {:p}", pointer);
|
||||||
@ -437,7 +444,6 @@ pub fn calibrate_L3_miss_hit(
|
|||||||
iterations: 1 << 11,
|
iterations: 1 << 11,
|
||||||
},
|
},
|
||||||
verbose_level,
|
verbose_level,
|
||||||
None,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
r.into_iter().next().unwrap()
|
r.into_iter().next().unwrap()
|
||||||
|
@ -1,16 +1,20 @@
|
|||||||
use crate::complex_addressing::CacheSlicing::{ComplexAddressing, Unsupported};
|
use crate::complex_addressing::CacheSlicing::{
|
||||||
|
ComplexAddressing, NoSlice, SimpleAddressing, Unsupported,
|
||||||
|
};
|
||||||
use cpuid::MicroArchitecture;
|
use cpuid::MicroArchitecture;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum CacheSlicing {
|
pub enum CacheSlicing {
|
||||||
Unsupported,
|
Unsupported,
|
||||||
ComplexAddressing(&'static [usize]),
|
ComplexAddressing(&'static [usize]),
|
||||||
SimpleAddressing(&'static usize),
|
SimpleAddressing(&'static usize),
|
||||||
NoSlice,
|
NoSlice,
|
||||||
}
|
}
|
||||||
const SANDYBRIDGE_TO_SKYLAKE_FUNCTIONS: [usize; 3] = [
|
const SANDYBRIDGE_TO_SKYLAKE_FUNCTIONS: [usize; 4] = [
|
||||||
0b0110_1101_0111_1101_0101_1101_0101_0001_000000,
|
0b0110_1101_0111_1101_0101_1101_0101_0001_000000,
|
||||||
0b1011_1010_1101_0111_1110_1010_1010_0010_000000,
|
0b1011_1010_1101_0111_1110_1010_1010_0010_000000,
|
||||||
0b1111_0011_0011_0011_0010_0100_1100_0100_000000,
|
0b1111_0011_0011_0011_0010_0100_1100_0100_000000,
|
||||||
|
0b0, // TODO
|
||||||
];
|
];
|
||||||
// missing functions for more than 8 cores.
|
// missing functions for more than 8 cores.
|
||||||
|
|
||||||
@ -26,28 +30,36 @@ pub fn cache_slicing(uarch: MicroArchitecture, physical_cores: u8) -> CacheSlici
|
|||||||
| MicroArchitecture::CoffeeLake => {
|
| MicroArchitecture::CoffeeLake => {
|
||||||
ComplexAddressing(&SANDYBRIDGE_TO_SKYLAKE_FUNCTIONS[0..((trailing_zeros + 1) as usize)])
|
ComplexAddressing(&SANDYBRIDGE_TO_SKYLAKE_FUNCTIONS[0..((trailing_zeros + 1) as usize)])
|
||||||
}
|
}
|
||||||
|
MicroArchitecture::SandyBridge => {
|
||||||
|
ComplexAddressing(&SANDYBRIDGE_TO_SKYLAKE_FUNCTIONS[0..((trailing_zeros) as usize)])
|
||||||
|
}
|
||||||
_ => Unsupported,
|
_ => Unsupported,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AddressHasher<'a> {
|
fn hash(addr: usize, mask: usize) -> usize {
|
||||||
masks: &'a [usize],
|
((addr & mask).count_ones() & 1) as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash(addr: usize, mask: usize) -> u32 {
|
impl CacheSlicing {
|
||||||
(addr & mask).count_ones() & 1
|
pub fn can_hash(&self) -> bool {
|
||||||
}
|
match self {
|
||||||
|
Unsupported | NoSlice => false,
|
||||||
impl AddressHasher<'_> {
|
ComplexAddressing(_) | SimpleAddressing(_) => true,
|
||||||
pub fn new(masks: &[usize]) -> AddressHasher {
|
}
|
||||||
AddressHasher { masks }
|
}
|
||||||
}
|
pub fn hash(&self, addr: usize) -> Option<usize> {
|
||||||
pub fn hash(&self, addr: usize) -> u32 {
|
match self {
|
||||||
let mut res = 0;
|
SimpleAddressing(&mask) => Some((addr & mask)),
|
||||||
for mask in self.masks {
|
ComplexAddressing(masks) => {
|
||||||
res <<= 1;
|
let mut res = 0;
|
||||||
res |= hash(addr, *mask);
|
for mask in *masks {
|
||||||
|
res <<= 1;
|
||||||
|
res |= hash(addr, *mask);
|
||||||
|
}
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
res
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user