Add prefetcher experiments
This commit is contained in:
parent
0807d3bda9
commit
84eee25e5a
@ -1,18 +1,23 @@
|
||||
use prefetcher_reverse::{Prober, PAGE_CACHELINE_LEN};
|
||||
use prefetcher_reverse::ip_tool::{Function, TIMED_MACCESS};
|
||||
use prefetcher_reverse::{pattern_helper, Prober, PAGE_CACHELINE_LEN};
|
||||
|
||||
pub const NUM_ITERATION: usize = 1 << 10;
|
||||
|
||||
fn exp(delay: u64) {
|
||||
fn exp(delay: u64, reload: &Function) {
|
||||
let mut prober = Prober::<2>::new(63).unwrap();
|
||||
prober.set_delay(delay);
|
||||
let pattern = (0usize..(PAGE_CACHELINE_LEN * 2usize)).collect::<Vec<usize>>();
|
||||
let result = prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
|
||||
let p = pattern_helper(pattern, reload);
|
||||
|
||||
let result = prober.full_page_probe(p, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let reload = Function::try_new(1, 0, TIMED_MACCESS).unwrap();
|
||||
|
||||
for delay in [0, 5, 10, 50] {
|
||||
println!("Delay after each access: {} us", delay);
|
||||
exp(delay);
|
||||
exp(delay, &reload);
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,10 @@ use cache_utils::mmap;
|
||||
use cache_utils::mmap::MMappedMemory;
|
||||
use flush_flush::{FFHandle, FFPrimitives, FlushAndFlush};
|
||||
use nix::Error;
|
||||
use prefetcher_reverse::{reference_patterns, Prober, CACHE_LINE_LEN, PAGE_CACHELINE_LEN};
|
||||
use prefetcher_reverse::ip_tool::{Function, TIMED_MACCESS};
|
||||
use prefetcher_reverse::{
|
||||
pattern_helper, reference_patterns, Prober, CACHE_LINE_LEN, PAGE_CACHELINE_LEN,
|
||||
};
|
||||
use rand::seq::SliceRandom;
|
||||
use std::iter::Cycle;
|
||||
use std::ops::Range;
|
||||
@ -18,19 +21,21 @@ use std::ops::Range;
|
||||
pub const NUM_ITERATION: usize = 1 << 10;
|
||||
pub const NUM_PAGES: usize = 256;
|
||||
|
||||
fn exp(delay: u64) {
|
||||
fn exp(delay: u64, reload: &Function) {
|
||||
for (name, pattern) in reference_patterns() {
|
||||
let p = pattern_helper(pattern, reload);
|
||||
let mut prober = Prober::<1>::new(63).unwrap();
|
||||
|
||||
println!("{}", name);
|
||||
let result = prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
|
||||
let result = prober.full_page_probe(p, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let reload = Function::try_new(1, 0, TIMED_MACCESS).unwrap();
|
||||
for delay in [0, 5, 10, 50] {
|
||||
println!("Delay after each access: {} us", delay);
|
||||
exp(delay);
|
||||
exp(delay, &reload);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,41 @@
|
||||
use prefetcher_reverse::{Prober, PAGE_CACHELINE_LEN};
|
||||
use cache_utils::{flush, maccess};
|
||||
use prefetcher_reverse::ip_tool::{Function, TIMED_MACCESS};
|
||||
use prefetcher_reverse::{pattern_helper, Prober, PAGE_CACHELINE_LEN};
|
||||
use std::arch::x86_64 as arch_x86;
|
||||
|
||||
pub const NUM_ITERATION: usize = 1 << 10;
|
||||
|
||||
fn exp(stride: usize, num_steps: i32, delay: u64) {
|
||||
unsafe extern "C" fn prefetch_l2(p: *const u8) -> u64 {
|
||||
maccess(p);
|
||||
arch_x86::_mm_mfence();
|
||||
flush(p);
|
||||
arch_x86::_mm_mfence();
|
||||
arch_x86::_mm_prefetch::<{ arch_x86::_MM_HINT_T1 }>(p as *const i8);
|
||||
arch_x86::__cpuid_count(0, 0);
|
||||
0
|
||||
}
|
||||
|
||||
unsafe extern "C" fn prefetch_l3(p: *const u8) -> u64 {
|
||||
maccess(p);
|
||||
arch_x86::_mm_mfence();
|
||||
flush(p);
|
||||
arch_x86::_mm_mfence();
|
||||
arch_x86::_mm_prefetch::<{ arch_x86::_MM_HINT_T2 }>(p as *const i8);
|
||||
arch_x86::__cpuid_count(0, 0);
|
||||
0
|
||||
}
|
||||
|
||||
unsafe extern "C" fn prefetch_l1(p: *const u8) -> u64 {
|
||||
maccess(p);
|
||||
arch_x86::_mm_mfence();
|
||||
flush(p);
|
||||
arch_x86::_mm_mfence();
|
||||
arch_x86::_mm_prefetch::<{ arch_x86::_MM_HINT_T0 }>(p as *const i8);
|
||||
arch_x86::__cpuid_count(0, 0);
|
||||
0
|
||||
}
|
||||
|
||||
fn exp(stride: usize, num_steps: i32, delay: u64, reload: &Function) {
|
||||
let mut prober = Prober::<2>::new(63).unwrap();
|
||||
prober.set_delay(delay);
|
||||
let limit = if num_steps < 0 {
|
||||
@ -11,23 +44,71 @@ fn exp(stride: usize, num_steps: i32, delay: u64) {
|
||||
stride * num_steps as usize
|
||||
};
|
||||
let pattern = (2usize..limit).step_by(stride).collect::<Vec<_>>();
|
||||
let result = prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
|
||||
let p = pattern_helper(pattern, reload);
|
||||
|
||||
let pl2 = Function {
|
||||
fun: prefetch_l2,
|
||||
ip: prefetch_l2 as *const u8,
|
||||
end: prefetch_l2 as *const u8,
|
||||
size: 0,
|
||||
};
|
||||
|
||||
let pl3 = Function {
|
||||
fun: prefetch_l3,
|
||||
ip: prefetch_l3 as *const u8,
|
||||
end: prefetch_l3 as *const u8,
|
||||
size: 0,
|
||||
};
|
||||
|
||||
let pl1 = Function {
|
||||
fun: prefetch_l1,
|
||||
ip: prefetch_l1 as *const u8,
|
||||
end: prefetch_l1 as *const u8,
|
||||
size: 0,
|
||||
};
|
||||
|
||||
let mut pattern_pl2 = pattern_helper((0..(2 * PAGE_CACHELINE_LEN)).collect(), &pl2);
|
||||
pattern_pl2.extend(p.iter().cloned());
|
||||
|
||||
let mut pattern_pl3 = pattern_helper((0..(2 * PAGE_CACHELINE_LEN)).collect(), &pl3);
|
||||
pattern_pl3.extend(p.iter().cloned());
|
||||
|
||||
let mut pattern_pl1 = pattern_helper((0..(2 * PAGE_CACHELINE_LEN)).collect(), &pl1);
|
||||
pattern_pl1.extend(p.iter().cloned());
|
||||
|
||||
println!("With no sw prefetch");
|
||||
let result = prober.full_page_probe(p, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result);
|
||||
println!("With L2 sw prefetch");
|
||||
let result = prober.full_page_probe(pattern_pl2, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result);
|
||||
println!("With L3 sw prefetch");
|
||||
let result = prober.full_page_probe(pattern_pl3, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result);
|
||||
println!("With L1 sw prefetch");
|
||||
let result = prober.full_page_probe(pattern_pl1, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for stride in [3, 4] {
|
||||
//let reload = Function::try_new(1, 0, TIMED_MACCESS).unwrap();
|
||||
let mut reloads = Vec::new();
|
||||
for i in 0..3 {
|
||||
reloads.push(Function::try_new(4, i, TIMED_MACCESS).unwrap());
|
||||
}
|
||||
for (index, stride) in [2, 3, 4].iter().enumerate() {
|
||||
let reload = &reloads[index];
|
||||
for delay_shift in [5, 12] {
|
||||
let limit = ((PAGE_CACHELINE_LEN + 32) / stride) as i32;
|
||||
//for num_steps in -1..limit {
|
||||
let num_steps = limit;
|
||||
println!(
|
||||
"Stride: {}, Limit: {}, Delay: {}",
|
||||
stride,
|
||||
*stride,
|
||||
num_steps,
|
||||
1 << delay_shift
|
||||
);
|
||||
exp(stride, num_steps, 1 << delay_shift);
|
||||
exp(*stride, num_steps, 1 << delay_shift, &reload);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
use prefetcher_reverse::{Prober, PAGE_CACHELINE_LEN};
|
||||
use prefetcher_reverse::ip_tool::{Function, TIMED_MACCESS};
|
||||
use prefetcher_reverse::{pattern_helper, Prober, PAGE_CACHELINE_LEN};
|
||||
|
||||
pub const NUM_ITERATION: usize = 1 << 10;
|
||||
|
||||
fn exp(stride: usize, num_steps: i32, delay: u64) {
|
||||
fn exp(stride: usize, num_steps: i32, delay: u64, reload: &Function) {
|
||||
let mut prober = Prober::<2>::new(63).unwrap();
|
||||
prober.set_delay(delay);
|
||||
let limit = if num_steps < 0 {
|
||||
@ -11,11 +12,15 @@ fn exp(stride: usize, num_steps: i32, delay: u64) {
|
||||
stride * num_steps as usize
|
||||
};
|
||||
let pattern = (2usize..limit).step_by(stride).collect::<Vec<_>>();
|
||||
let result = prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
|
||||
let p = pattern_helper(pattern, reload);
|
||||
|
||||
let result = prober.full_page_probe(p, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let reload = Function::try_new(1, 0, TIMED_MACCESS).unwrap();
|
||||
|
||||
for stride in [5, 7, 8] {
|
||||
for delay_shift in [5, 12, 20] {
|
||||
//let stride = 8;
|
||||
@ -28,7 +33,7 @@ fn main() {
|
||||
num_steps,
|
||||
1 << delay_shift
|
||||
);
|
||||
exp(stride, num_steps, 1 << delay_shift);
|
||||
exp(stride, num_steps, 1 << delay_shift, &reload);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
@ -32,22 +32,25 @@ pub struct FunctionTemplate {
|
||||
end: *const u8,
|
||||
}
|
||||
|
||||
// Note those fields should not be public
|
||||
// We need a way to also take care of non allocated functions.
|
||||
#[derive(Debug)]
|
||||
pub struct Function {
|
||||
fun: unsafe extern "C" fn(*const u8) -> u64,
|
||||
ip: *const u8,
|
||||
end: *const u8,
|
||||
size: usize,
|
||||
pub fun: unsafe extern "C" fn(*const u8) -> u64,
|
||||
pub ip: *const u8,
|
||||
pub end: *const u8,
|
||||
pub size: usize,
|
||||
}
|
||||
lazy_static! {
|
||||
static ref wx_allocator: Mutex<WXAllocator> = Mutex::new(WXAllocator::new());
|
||||
}
|
||||
const TIMED_MACCESS: FunctionTemplate = FunctionTemplate {
|
||||
pub const TIMED_MACCESS: FunctionTemplate = FunctionTemplate {
|
||||
start: timed_maccess_template,
|
||||
ip: timed_maccess_template_ip as *const u8,
|
||||
end: timed_maccess_template_end as *const u8,
|
||||
};
|
||||
|
||||
const TIMED_CLFLUSH: FunctionTemplate = FunctionTemplate {
|
||||
pub const TIMED_CLFLUSH: FunctionTemplate = FunctionTemplate {
|
||||
start: timed_clflush_template,
|
||||
ip: timed_clflush_template_ip as *const u8,
|
||||
end: timed_clflush_template_end as *const u8,
|
||||
|
@ -26,6 +26,8 @@ use std::{thread, time};
|
||||
|
||||
pub mod ip_tool;
|
||||
|
||||
use ip_tool::Function;
|
||||
|
||||
// NB these may need to be changed / dynamically measured.
|
||||
pub const CACHE_LINE_LEN: usize = 64;
|
||||
pub const PAGE_CACHELINE_LEN: usize = PAGE_LEN / CACHE_LINE_LEN;
|
||||
@ -58,9 +60,15 @@ pub enum ProbeType {
|
||||
FullFlush,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PatternAccess<'a> {
|
||||
pub function: &'a Function,
|
||||
pub offset: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProbePattern {
|
||||
pub pattern: Vec<usize>,
|
||||
pub struct ProbePattern<'a> {
|
||||
pub pattern: Vec<PatternAccess<'a>>,
|
||||
pub probe: Probe,
|
||||
}
|
||||
|
||||
@ -105,8 +113,8 @@ pub struct DualProbeResult {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FullPageDualProbeResults {
|
||||
pub pattern: Vec<usize>,
|
||||
pub struct FullPageDualProbeResults<'a> {
|
||||
pub pattern: Vec<PatternAccess<'a>>,
|
||||
pub num_iteration: u32,
|
||||
pub single_probe_results: Vec<DualProbeResult>,
|
||||
pub full_flush_results: DPRItem<FullPR>,
|
||||
@ -120,8 +128,8 @@ pub struct SingleProbeResult {
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FullPageSingleProbeResult<const GS: usize> {
|
||||
pub pattern: Vec<usize>,
|
||||
pub struct FullPageSingleProbeResult<'a, const GS: usize> {
|
||||
pub pattern: Vec<PatternAccess<'a>>,
|
||||
pub probe_type: ProbeType,
|
||||
pub num_iteration: u32,
|
||||
pub results: Vec<SingleProbeResult>,
|
||||
@ -243,15 +251,14 @@ impl<const GS: usize> Prober<GS> {
|
||||
unsafe { self.ff_channel.prepare(&mut ff_handles) };
|
||||
|
||||
let mut pattern_res = vec![0; pattern.pattern.len()];
|
||||
for (i, offset) in pattern.pattern.iter().enumerate() {
|
||||
let h = &mut self.fr_handles[page_index][*offset];
|
||||
pattern_res[i] = unsafe { self.fr_channel.test_debug(h, false) }.unwrap().1;
|
||||
for (i, access) in pattern.pattern.iter().enumerate() {
|
||||
let h = &mut self.fr_handles[page_index][access.offset];
|
||||
let pointer: *const u8 = h.to_const_u8_pointer();
|
||||
pattern_res[i] = unsafe { (access.function.fun)(pointer) };
|
||||
// TODO IP : This is where the pattern access need to be done using pattern.function instead.
|
||||
//pattern_res[i] = unsafe { self.fr_channel.test_debug(h, false) }.unwrap().1;
|
||||
delay(self.delay);
|
||||
/*if self.delay > 0 {
|
||||
thread::sleep(time::Duration::from_nanos(self.delay)); // FIXME parameter magic
|
||||
}*/
|
||||
//pattern_res[i] = unsafe { self.fr_channel.test_single(h, false) }.unwrap()
|
||||
//pattern_res[i] = Miss;
|
||||
//pattern_res[i] = unsafe { self.fr_channel.test_single(h, false) }.unwrap();
|
||||
//unsafe { only_reload(h.to_const_u8_pointer()) };
|
||||
}
|
||||
|
||||
@ -329,13 +336,13 @@ impl<const GS: usize> Prober<GS> {
|
||||
result
|
||||
}
|
||||
|
||||
fn full_page_probe_helper(
|
||||
fn full_page_probe_helper<'a>(
|
||||
&mut self,
|
||||
pattern: &mut ProbePattern,
|
||||
pattern: &mut ProbePattern<'a>,
|
||||
probe_type: ProbeType,
|
||||
num_iteration: u32,
|
||||
warmup: u32,
|
||||
) -> FullPageSingleProbeResult<GS> {
|
||||
) -> FullPageSingleProbeResult<'a, GS> {
|
||||
let mut result = FullPageSingleProbeResult {
|
||||
pattern: pattern.pattern.clone(),
|
||||
probe_type,
|
||||
@ -362,12 +369,12 @@ impl<const GS: usize> Prober<GS> {
|
||||
result
|
||||
}
|
||||
|
||||
pub fn full_page_probe(
|
||||
pub fn full_page_probe<'a>(
|
||||
&mut self,
|
||||
pattern: Vec<usize>,
|
||||
pattern: Vec<PatternAccess<'a>>,
|
||||
num_iteration: u32,
|
||||
warmup: u32,
|
||||
) -> FullPageDualProbeResults {
|
||||
) -> FullPageDualProbeResults<'a> {
|
||||
let mut probe_pattern = ProbePattern {
|
||||
pattern: pattern,
|
||||
probe: Probe::FullFlush,
|
||||
@ -417,13 +424,13 @@ impl<const GS: usize> Prober<GS> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FullPageDualProbeResults {
|
||||
impl<'a> Display for FullPageDualProbeResults<'a> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let mut indices = vec![None; self.single_probe_results.len()];
|
||||
let pat_len = self.pattern.len();
|
||||
let divider = (self.single_probe_results.len() * self.num_iteration as usize) as f32;
|
||||
for (i, &offset) in self.pattern.iter().enumerate() {
|
||||
indices[offset] = Some(i);
|
||||
for (i, access) in self.pattern.iter().enumerate() {
|
||||
indices[access.offset] = Some(i);
|
||||
}
|
||||
// Display header
|
||||
let mut r = writeln!(
|
||||
@ -529,3 +536,13 @@ pub fn reference_patterns() -> [(&'static str, Vec<usize>); 9] {
|
||||
("Pattern 5 (IV)", vec![0, 1, 2, 63, 62, 61, 19]),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn pattern_helper<'a>(offsets: Vec<usize>, function: &'a Function) -> Vec<PatternAccess<'a>> {
|
||||
offsets
|
||||
.into_iter()
|
||||
.map(|i| PatternAccess {
|
||||
function,
|
||||
offset: i,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -10,7 +10,10 @@ use cache_utils::mmap;
|
||||
use cache_utils::mmap::MMappedMemory;
|
||||
use flush_flush::{FFHandle, FFPrimitives, FlushAndFlush};
|
||||
use nix::Error;
|
||||
use prefetcher_reverse::{Prober, CACHE_LINE_LEN, PAGE_CACHELINE_LEN};
|
||||
use prefetcher_reverse::ip_tool::{Function, TIMED_MACCESS};
|
||||
use prefetcher_reverse::{
|
||||
pattern_helper, PatternAccess, Prober, CACHE_LINE_LEN, PAGE_CACHELINE_LEN,
|
||||
};
|
||||
use rand::seq::SliceRandom;
|
||||
use std::iter::Cycle;
|
||||
|
||||
@ -196,8 +199,10 @@ fn main() {
|
||||
}
|
||||
}*/
|
||||
|
||||
let pattern = generate_pattern(0, 3, 12).unwrap();
|
||||
let pattern4 = generate_pattern(0, 4, 12).unwrap();
|
||||
let reload = Function::try_new(1, 0, TIMED_MACCESS).unwrap();
|
||||
|
||||
let pattern = pattern_helper(generate_pattern(0, 3, 12).unwrap(), &reload);
|
||||
let pattern4 = pattern_helper(generate_pattern(0, 4, 12).unwrap(), &reload);
|
||||
let mut new_prober = Prober::<1>::new(63).unwrap();
|
||||
let result = new_prober.full_page_probe(pattern.clone(), NUM_ITERATION as u32, 100);
|
||||
println!("{}", result);
|
||||
@ -207,27 +212,27 @@ fn main() {
|
||||
println!("{}", result2);
|
||||
let result4 = new_prober.full_page_probe(pattern4, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result4);
|
||||
let pattern5 = generate_pattern(0, 5, 8).unwrap();
|
||||
let pattern5 = pattern_helper(generate_pattern(0, 5, 8).unwrap(), &reload);
|
||||
let result5 = new_prober.full_page_probe(pattern5, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result5);
|
||||
|
||||
let pattern5 = generate_pattern(0, 5, 4).unwrap();
|
||||
let pattern5 = pattern_helper(generate_pattern(0, 5, 4).unwrap(), &reload);
|
||||
let result5 = new_prober.full_page_probe(pattern5, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result5);
|
||||
|
||||
let pattern = generate_pattern(0, 10, 4).unwrap();
|
||||
let pattern = pattern_helper(generate_pattern(0, 10, 4).unwrap(), &reload);
|
||||
let result = new_prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result);
|
||||
|
||||
let pattern = generate_pattern(0, 6, 8).unwrap();
|
||||
let pattern = pattern_helper(generate_pattern(0, 6, 8).unwrap(), &reload);
|
||||
let result = new_prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result);
|
||||
|
||||
let pattern = generate_pattern(2, 6, 0).unwrap();
|
||||
let pattern = pattern_helper(generate_pattern(2, 6, 0).unwrap(), &reload);
|
||||
let result = new_prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result);
|
||||
|
||||
let pattern = vec![0, 0, 8, 8, 16, 16, 24, 24];
|
||||
let pattern = pattern_helper(vec![0, 0, 8, 8, 16, 16, 24, 24], &reload);
|
||||
let result = new_prober.full_page_probe(pattern, NUM_ITERATION as u32, 100);
|
||||
println!("{}", result);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user