From 50026c9f654cfd8a0758840204f0570943f758ba Mon Sep 17 00:00:00 2001 From: Filipe Rodrigues Date: Wed, 31 May 2023 19:57:11 +0100 Subject: [PATCH] Added `page-temperature-density` graph. --- .vscode/settings.json | 3 +- ftmemsim-graphs/src/args.rs | 25 ++++++++ ftmemsim-graphs/src/main.rs | 120 +++++++++++++++++++++++++++++++++++- run.sh | 50 ++++++++++++++- 4 files changed, 192 insertions(+), 6 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index b1bef84..98aef9a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,6 +13,7 @@ "optane", "pico", "PICOS", - "plotlib" + "plotlib", + "powf" ] } diff --git a/ftmemsim-graphs/src/args.rs b/ftmemsim-graphs/src/args.rs index ae78f7b..f829386 100644 --- a/ftmemsim-graphs/src/args.rs +++ b/ftmemsim-graphs/src/args.rs @@ -70,6 +70,31 @@ pub enum SubCmd { #[clap(flatten)] output: ArgsOutputFile, }, + + /// Page temperature density + #[clap(name = "page-temperature-density")] + PageTemperatureDensity { + /// Input + input_file: PathBuf, + + /// Output + #[clap(flatten)] + output: ArgsOutputFile, + + /// Temperature exponent + #[clap(long = "temp-exponent", default_value_t = 1.0)] + temp_exponent: f64, + + /// Read weight for temperature + #[clap(long = "temp-read-weight", default_value_t = 1.0)] + #[clap(allow_hyphen_values = true)] + temp_read_weight: f64, + + /// Write weight for temperature + #[clap(long = "temp-write-weight", default_value_t = 2.0)] + #[clap(allow_hyphen_values = true)] + temp_write_weight: f64, + }, } /// Output file diff --git a/ftmemsim-graphs/src/main.rs b/ftmemsim-graphs/src/main.rs index 44f4c25..b0b3936 100644 --- a/ftmemsim-graphs/src/main.rs +++ b/ftmemsim-graphs/src/main.rs @@ -1,7 +1,7 @@ //! Creates graphs from `ftmemsim`'s output // Features -#![feature(lint_reasons)] +#![feature(lint_reasons, array_windows, float_minimum_maximum)] // Modules mod args; @@ -16,7 +16,7 @@ use { gzp::par::decompress::ParDecompress, itertools::Itertools, std::{ - collections::{BTreeMap, HashMap}, + collections::{BTreeMap, HashMap, VecDeque}, path::Path, }, }; @@ -320,6 +320,122 @@ fn main() -> Result<(), anyhow::Error> { self::save_plot(&output.file, &mut fg, output.width, output.height).context("Unable to save plot")?; }, + + args::SubCmd::PageTemperatureDensity { + input_file, + output, + temp_exponent, + temp_read_weight, + temp_write_weight, + } => { + // Parse the input file + let data = self::read_data(&input_file)?; + + let (min_time, max_time) = data + .hemem + .page_accesses + .accesses + .iter() + .map(|page_access| page_access.time) + .minmax() + .into_option() + .unwrap_or((0, 1)); + + // Then index the page pointers. + // Note: We do this because the page pointers are very far away, value-wise, which + // causes them to display far away in the graph. Since the actual values of the + // pages don't matter to us, we just index them by order of appearance. + let page_ptr_idxs = data + .hemem + .page_migrations + .migrations + .iter() + .enumerate() + .map(|(idx, (page_ptr, _))| (page_ptr, idx)) + .collect::>(); + + + // Get all the points + let mut cur_temps = HashMap::::new(); + let points = data + .hemem + .page_accesses + .accesses + .iter() + .group_by(|page_access| page_access.page_ptr) + .into_iter() + .map(|(page_ptr, page_accesses)| { + let mut temps = page_accesses + .map(|page_access| { + let cur_temp = cur_temps.entry(page_ptr).or_insert(0.0); + match page_access.kind { + ftmemsim::data::PageAccessKind::Read => *cur_temp += temp_read_weight, + ftmemsim::data::PageAccessKind::Write => *cur_temp += temp_write_weight, + }; + + (page_access.time, *cur_temp) + }) + .sorted_by_key(|&(time, _)| time) + .collect::>(); + + let last_temp = temps.back().map_or(0.0, |&(_, temp)| temp); + temps.push_front((min_time, 0.0)); + temps.push_back((max_time, last_temp)); + + (page_ptr, Vec::from(temps)) + }) + .collect::>(); + + let max_temp = points + .values() + .flat_map(|temps| temps.iter().map(|&(_, temp)| temp)) + .max_by(f64::total_cmp) + .unwrap_or(0.0); + + // Finally create and save the plot + let mut fg = gnuplot::Figure::new(); + let fg_axes2d: &mut gnuplot::Axes2D = fg.axes2d(); + for (&page_ptr, temps) in &points { + let page_ptr_idx = *page_ptr_idxs.get(&page_ptr).expect("Page ptr had no index"); + + for &[(prev_time2, prev_temp), (cur_time, cur_temp)] in temps.array_windows::<2>() { + let prev_time = (prev_time2 - min_time) as f64 / (max_time - min_time) as f64; + let cur_time = (cur_time - min_time) as f64 / (max_time - min_time) as f64; + + let start_color = (1.0, 0.0, 0.0); + let end_color = (0.0, 1.0, 0.0); + + let progress = (prev_temp + cur_temp) / (2.0 * max_temp); + let progress = progress.powf(temp_exponent); + + let color = ( + start_color.0 * (1.0 - progress) + end_color.0 * progress, + start_color.1 * (1.0 - progress) + end_color.1 * progress, + start_color.2 * (1.0 - progress) + end_color.2 * progress, + ); + let color = format!( + "#{:02x}{:02x}{:02x}", + (color.0 * 255.0) as u8, + (color.1 * 255.0) as u8, + (color.2 * 255.0) as u8, + ); + + fg_axes2d.fill_between([prev_time, cur_time], [page_ptr_idx; 2], [page_ptr_idx + 1; 2], &[ + PlotOption::Color(&color), + PlotOption::FillAlpha(1.0), + PlotOption::FillRegion(FillRegionType::Below), + ]); + } + } + + fg_axes2d + .set_x_label("Time (normalized)", &[]) + .set_y_label("Page (indexed)", &[]) + .set_x_range(AutoOption::Fix(0.0), AutoOption::Fix(1.0)) + .set_y_range(AutoOption::Fix(0.0), AutoOption::Fix(page_ptr_idxs.len() as f64)); + + self::save_plot(&output.file, &mut fg, output.width, output.height).context("Unable to save plot")?; + }, } Ok(()) diff --git a/run.sh b/run.sh index dd4ad50..9e6ae50 100755 --- a/run.sh +++ b/run.sh @@ -32,6 +32,8 @@ cargo run --profile "$PROFILE" -p ftmemsim -- \ --output "$OUTPUT_FILE" echo "Creating graphs" +cargo build --profile "$PROFILE" -p ftmemsim-graphs + cargo run --profile "$PROFILE" -p ftmemsim-graphs -- \ --log-file-append \ --log-file "$LOG_FILE" \ @@ -39,7 +41,8 @@ cargo run --profile "$PROFILE" -p ftmemsim-graphs -- \ "$OUTPUT_FILE" \ --output "resources/data/page_migrations.$GRAPH_OUTPUT_FORMAT" \ --output-width "$GRAPH_OUTPUT_WIDTH" \ - --output-height "$GRAPH_OUTPUT_HEIGHT" + --output-height "$GRAPH_OUTPUT_HEIGHT" \ + & cargo run --profile "$PROFILE" -p ftmemsim-graphs -- \ --log-file-append \ @@ -48,7 +51,8 @@ cargo run --profile "$PROFILE" -p ftmemsim-graphs -- \ "$OUTPUT_FILE" \ --output "resources/data/page_migrations_hist.$GRAPH_OUTPUT_FORMAT" \ --output-width "$GRAPH_OUTPUT_WIDTH" \ - --output-height "$GRAPH_OUTPUT_HEIGHT" + --output-height "$GRAPH_OUTPUT_HEIGHT" \ + & cargo run --profile "$PROFILE" -p ftmemsim-graphs -- \ --log-file-append \ @@ -57,4 +61,44 @@ cargo run --profile "$PROFILE" -p ftmemsim-graphs -- \ "$OUTPUT_FILE" \ --output "resources/data/page_temperature.$GRAPH_OUTPUT_FORMAT" \ --output-width "$GRAPH_OUTPUT_WIDTH" \ - --output-height "$GRAPH_OUTPUT_HEIGHT" + --output-height "$GRAPH_OUTPUT_HEIGHT" \ + & + +cargo run --profile "$PROFILE" -p ftmemsim-graphs -- \ + --log-file-append \ + --log-file "$LOG_FILE" \ + page-temperature-density \ + "$OUTPUT_FILE" \ + --output "resources/data/page_temperature_density.$GRAPH_OUTPUT_FORMAT" \ + --output-width "$GRAPH_OUTPUT_WIDTH" \ + --output-height "$GRAPH_OUTPUT_HEIGHT" \ + --temp-exponent "0.15" \ + --temp-read-weight "1.0" \ + --temp-write-weight "2.0" \ + & + +cargo run --profile "$PROFILE" -p ftmemsim-graphs -- \ + --log-file-append \ + --log-file "$LOG_FILE" \ + page-temperature-density \ + "$OUTPUT_FILE" \ + --output "resources/data/page_temperature_density.read.$GRAPH_OUTPUT_FORMAT" \ + --output-width "$GRAPH_OUTPUT_WIDTH" \ + --output-height "$GRAPH_OUTPUT_HEIGHT" \ + --temp-exponent "0.15" \ + --temp-write-weight "0.0" \ + & + +cargo run --profile "$PROFILE" -p ftmemsim-graphs -- \ + --log-file-append \ + --log-file "$LOG_FILE" \ + page-temperature-density \ + "$OUTPUT_FILE" \ + --output "resources/data/page_temperature_density.write.$GRAPH_OUTPUT_FORMAT" \ + --output-width "$GRAPH_OUTPUT_WIDTH" \ + --output-height "$GRAPH_OUTPUT_HEIGHT" \ + --temp-exponent "0.15" \ + --temp-read-weight "0.0" \ + & + +wait