Reformat, fix a bug due to confusing p and pointer in calibrate two thread and add relaod support

This commit is contained in:
GuillaumeDIDIER 2020-07-07 15:07:55 +02:00
parent d47a7167ff
commit daaca820fd
2 changed files with 134 additions and 90 deletions

View File

@ -1,12 +1,16 @@
use core::sync::atomic::{AtomicBool,Ordering}; use cache_utils::calibration::{
calibrate_fixed_freq_2_thread, flush_and_reload, load_and_flush, only_flush, only_reload,
reload_and_flush, CalibrateOperation2T, HistParams, Verbosity, CFLUSH_BUCKET_NUMBER,
CFLUSH_BUCKET_SIZE, CFLUSH_NUM_ITER,
};
use cache_utils::mmap::MMappedMemory;
use cache_utils::{flush, maccess, noop};
use core::sync::atomic::spin_loop_hint; use core::sync::atomic::spin_loop_hint;
use core::sync::atomic::{AtomicBool, Ordering};
use nix::sched::{sched_getaffinity, CpuSet};
use nix::unistd::Pid;
use std::sync::Arc; use std::sync::Arc;
use std::thread; use std::thread;
use cache_utils::mmap::MMappedMemory;
use nix::sched::{CpuSet, sched_getaffinity};
use cache_utils::calibration::{calibrate_fixed_freq_2_thread, CalibrateOperation2T, load_and_flush, HistParams, CFLUSH_BUCKET_NUMBER, CFLUSH_BUCKET_SIZE, CFLUSH_NUM_ITER, Verbosity, only_flush};
use cache_utils::{maccess, noop, flush};
use nix::unistd::Pid;
/* /*
fn wait(turn_lock: &AtomicBool, turn: bool) { fn wait(turn_lock: &AtomicBool, turn: bool) {
@ -117,54 +121,79 @@ fn main() {
if pointer as usize & (cache_line_size - 1) != 0 { if pointer as usize & (cache_line_size - 1) != 0 {
panic!("not aligned nicely"); panic!("not aligned nicely");
} }
calibrate_fixed_freq_2_thread(pointer, calibrate_fixed_freq_2_thread(
64, pointer,
array.len() as isize, 64,
&mut core_pairs.into_iter(), array.len() as isize,
&[ &mut core_pairs.into_iter(),
CalibrateOperation2T { &[
prepare: multiple_access, CalibrateOperation2T {
op: only_flush, prepare: multiple_access,
name: "clflush_remote_hit", op: only_flush,
display_name: "clflush remote hit", name: "clflush_remote_hit",
}, display_name: "clflush remote hit",
CalibrateOperation2T { },
prepare: multiple_access, CalibrateOperation2T {
op: load_and_flush, prepare: multiple_access,
name: "clflush_shared_hit", op: load_and_flush,
display_name: "clflush shared hit", name: "clflush_shared_hit",
}, display_name: "clflush shared hit",
CalibrateOperation2T { },
prepare: flush, CalibrateOperation2T {
op: only_flush, prepare: flush,
name: "clflush_miss_f", op: only_flush,
display_name: "clflush miss - f", name: "clflush_miss_f",
}, display_name: "clflush miss - f",
CalibrateOperation2T { },
prepare: flush, CalibrateOperation2T {
op: load_and_flush, prepare: flush,
name: "clflush_local_hit_f", op: load_and_flush,
display_name: "clflush local hit - f", name: "clflush_local_hit_f",
}, display_name: "clflush local hit - f",
CalibrateOperation2T { },
prepare: noop::<u8>, CalibrateOperation2T {
op: only_flush, prepare: noop::<u8>,
name: "clflush_miss_n", op: only_flush,
display_name: "clflush miss - n", name: "clflush_miss_n",
}, display_name: "clflush miss - n",
CalibrateOperation2T { },
prepare: noop::<u8>, CalibrateOperation2T {
op: load_and_flush, prepare: noop::<u8>,
name: "clflush_local_hit_n", op: load_and_flush,
display_name: "clflush local hit - n", name: "clflush_local_hit_n",
}, display_name: "clflush local hit - n",
], },
HistParams { CalibrateOperation2T {
bucket_number: CFLUSH_BUCKET_NUMBER, prepare: noop::<u8>,
bucket_size: CFLUSH_BUCKET_SIZE, op: flush_and_reload,
iterations: CFLUSH_NUM_ITER, name: "reload_miss",
}, display_name: "reload miss",
verbose_level, },
CalibrateOperation2T {
prepare: multiple_access,
op: reload_and_flush,
name: "reload_remote_hit",
display_name: "reload remote hit",
},
CalibrateOperation2T {
prepare: multiple_access,
op: only_reload,
name: "reload_shared_hit",
display_name: "reload shared hit",
},
CalibrateOperation2T {
prepare: noop::<u8>,
op: only_reload,
name: "reload_local_hit",
display_name: "reload local hit",
},
],
HistParams {
bucket_number: CFLUSH_BUCKET_NUMBER,
bucket_size: CFLUSH_BUCKET_SIZE,
iterations: CFLUSH_NUM_ITER,
},
verbose_level,
); );
} }
} }

View File

@ -1,6 +1,6 @@
#![allow(clippy::missing_safety_doc)] #![allow(clippy::missing_safety_doc)]
use crate::complex_addressing::{cache_slicing}; use crate::complex_addressing::cache_slicing;
use crate::{flush, maccess, rdtsc_fence}; use crate::{flush, maccess, rdtsc_fence};
use cpuid::MicroArchitecture; use cpuid::MicroArchitecture;
@ -18,24 +18,23 @@ use nix::unistd::Pid;
//#[cfg(feature = "use_std")] //#[cfg(feature = "use_std")]
//use nix::Error::Sys; //use nix::Error::Sys;
#[cfg(feature = "use_std")] #[cfg(feature = "use_std")]
use nix::Error;
#[cfg(feature = "use_std")]
use std::sync::Arc; use std::sync::Arc;
#[cfg(feature = "use_std")] #[cfg(feature = "use_std")]
use std::thread; use std::thread;
#[cfg(feature = "use_std")]
use nix::Error;
extern crate alloc; extern crate alloc;
use crate::calibration::Verbosity::*; use crate::calibration::Verbosity::*;
use alloc::vec; use alloc::vec;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::cmp::min; use core::cmp::min;
use core::ptr::null_mut;
use core::sync::atomic::{spin_loop_hint, AtomicBool, AtomicPtr, Ordering};
use itertools::Itertools; use itertools::Itertools;
use core::sync::atomic::{AtomicPtr, AtomicBool, Ordering, spin_loop_hint};
use core::ptr::{/*null,*/ null_mut};
use atomic::Atomic; use atomic::Atomic;
#[derive(Ord, PartialOrd, Eq, PartialEq)] #[derive(Ord, PartialOrd, Eq, PartialEq)]
pub enum Verbosity { pub enum Verbosity {
NoOutput, NoOutput,
@ -61,6 +60,12 @@ pub unsafe fn flush_and_reload(p: *const u8) -> u64 {
only_reload(p) only_reload(p)
} }
pub unsafe fn reload_and_flush(p: *const u8) -> u64 {
let r = only_reload(p);
flush(p);
r
}
pub unsafe fn only_flush(p: *const u8) -> u64 { pub unsafe fn only_flush(p: *const u8) -> u64 {
let t = rdtsc_fence(); let t = rdtsc_fence();
flush(p); flush(p);
@ -272,8 +277,6 @@ 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() { let slicing = if let Some(uarch) = MicroArchitecture::get_micro_architecture() {
Some(cache_slicing(uarch, 8)) Some(cache_slicing(uarch, 8))
} else { } else {
@ -446,7 +449,7 @@ pub struct CalibrateResult2T {
pub helper_core: usize, pub helper_core: usize,
pub res: Result<Vec<CalibrateResult>, nix::Error>, // TODO pub res: Result<Vec<CalibrateResult>, nix::Error>, // TODO
// TODO // TODO
} }
fn wait(turn_lock: &AtomicBool, turn: bool) { fn wait(turn_lock: &AtomicBool, turn: bool) {
@ -470,7 +473,15 @@ pub unsafe fn calibrate_fixed_freq_2_thread<I: Iterator<Item = (usize, usize)>>(
hist_params: HistParams, hist_params: HistParams,
verbosity_level: Verbosity, verbosity_level: Verbosity,
) -> Vec<CalibrateResult2T> { ) -> Vec<CalibrateResult2T> {
calibrate_fixed_freq_2_thread_impl(p, increment, len, cores, operations, hist_params, verbosity_level) calibrate_fixed_freq_2_thread_impl(
p,
increment,
len,
cores,
operations,
hist_params,
verbosity_level,
)
} }
#[cfg(feature = "use_std")] #[cfg(feature = "use_std")]
@ -514,15 +525,13 @@ fn calibrate_fixed_freq_2_thread_impl<I: Iterator<Item = (usize, usize)>>(
let mut ret = Vec::new(); let mut ret = Vec::new();
let helper_thread_params = Arc::new(HelperThreadParams{ let helper_thread_params = Arc::new(HelperThreadParams {
turn: AtomicBool::new(false), turn: AtomicBool::new(false),
stop: AtomicBool::new(true), stop: AtomicBool::new(true),
op: Atomic::new(operations[0].prepare), op: Atomic::new(operations[0].prepare),
address: AtomicPtr::new(null_mut()), address: AtomicPtr::new(null_mut()),
}); });
if verbosity_level >= Thresholds { if verbosity_level >= Thresholds {
print!("CSV: main_core, helper_core, address, "); print!("CSV: main_core, helper_core, address, ");
if h.is_some() { if h.is_some() {
@ -565,47 +574,57 @@ fn calibrate_fixed_freq_2_thread_impl<I: Iterator<Item = (usize, usize)>>(
// set main thread affinity // set main thread affinity
if verbosity_level >= Thresholds { if verbosity_level >= Thresholds {
println!("Calibration for main_core {}, helper {}.", main_core, helper_core); println!(
"Calibration for main_core {}, helper {}.",
main_core, helper_core
);
} }
eprintln!("Calibration for main_core {}, helper {}.", main_core, helper_core); eprintln!(
"Calibration for main_core {}, helper {}.",
main_core, helper_core
);
let mut core = CpuSet::new(); let mut core = CpuSet::new();
match core.set(main_core) { match core.set(main_core) {
Ok(_) => {}, Ok(_) => {}
Err(e) => { Err(e) => {
ret.push(CalibrateResult2T{main_core, helper_core, res:Err(e)}); ret.push(CalibrateResult2T {
main_core,
helper_core,
res: Err(e),
});
continue; continue;
} }
} }
match sched_setaffinity(Pid::from_raw(0), &core) { match sched_setaffinity(Pid::from_raw(0), &core) {
Ok(_) => {}, Ok(_) => {}
Err(e) => { Err(e) => {
ret.push(CalibrateResult2T{main_core, helper_core, res:Err(e)}); ret.push(CalibrateResult2T {
main_core,
helper_core,
res: Err(e),
});
continue; continue;
} }
} }
helper_thread_params.stop.store(false, Ordering::Relaxed); helper_thread_params.stop.store(false, Ordering::Relaxed);
// set up the helper thread // set up the helper thread
let htp = helper_thread_params.clone(); let htp = helper_thread_params.clone();
let hc = helper_core; let hc = helper_core;
let helper_thread = thread::spawn(move || { let helper_thread = thread::spawn(move || calibrate_fixed_freq_2_thread_helper(htp, hc));
calibrate_fixed_freq_2_thread_helper(htp, hc)
});
// do the calibration // do the calibration
let mut calibrate_result_vec = Vec::new(); let mut calibrate_result_vec = Vec::new();
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) };
helper_thread_params.address.store(p as *mut u8, Ordering::Relaxed); helper_thread_params
.address
.store(pointer as *mut u8, Ordering::Relaxed);
let hash = h.map(|h| h(pointer as usize)); let hash = h.map(|h| h(pointer as usize));
@ -627,8 +646,6 @@ fn calibrate_fixed_freq_2_thread_impl<I: Iterator<Item = (usize, usize)>>(
}; };
calibrate_result.histogram.reserve(operations.len()); calibrate_result.histogram.reserve(operations.len());
for op in operations { for op in operations {
helper_thread_params.op.store(op.prepare, Ordering::Relaxed); helper_thread_params.op.store(op.prepare, Ordering::Relaxed);
let mut hist = vec![0; hist_params.bucket_number]; let mut hist = vec![0; hist_params.bucket_number];
@ -718,10 +735,10 @@ fn calibrate_fixed_freq_2_thread_impl<I: Iterator<Item = (usize, usize)>>(
calibrate_result_vec.push(calibrate_result); calibrate_result_vec.push(calibrate_result);
} }
ret.push(CalibrateResult2T{ ret.push(CalibrateResult2T {
main_core, main_core,
helper_core, helper_core,
res: Ok(calibrate_result_vec) res: Ok(calibrate_result_vec),
}); });
// terminate the thread // terminate the thread
helper_thread_params.stop.store(true, Ordering::Relaxed); helper_thread_params.stop.store(true, Ordering::Relaxed);
@ -729,7 +746,6 @@ fn calibrate_fixed_freq_2_thread_impl<I: Iterator<Item = (usize, usize)>>(
wait(&helper_thread_params.turn, false); wait(&helper_thread_params.turn, false);
// join thread. // join thread.
helper_thread.join(); helper_thread.join();
} }
sched_setaffinity(Pid::from_raw(0), &old).unwrap(); sched_setaffinity(Pid::from_raw(0), &old).unwrap();
@ -754,17 +770,16 @@ fn calibrate_fixed_freq_2_thread_helper(
// set thread affinity // set thread affinity
let mut core = CpuSet::new(); let mut core = CpuSet::new();
match core.set(helper_core) { match core.set(helper_core) {
Ok(_) => {}, Ok(_) => {}
Err(_e) => { Err(_e) => {
unimplemented!(); unimplemented!();
} }
} }
match sched_setaffinity(Pid::from_raw(0), &core) { match sched_setaffinity(Pid::from_raw(0), &core) {
Ok(_) => {}, Ok(_) => {}
Err(_e) => { Err(_e) => {
unimplemented!(); unimplemented!();
} }
} }
@ -778,7 +793,7 @@ fn calibrate_fixed_freq_2_thread_helper(
// get the relevant parameters // get the relevant parameters
let addr: *const u8 = params.address.load(Ordering::Relaxed); let addr: *const u8 = params.address.load(Ordering::Relaxed);
let op = params.op.load(Ordering::Relaxed); let op = params.op.load(Ordering::Relaxed);
unsafe {op(addr)}; unsafe { op(addr) };
// release lock // release lock
next(&params.turn); next(&params.turn);
} }