Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
nviennot
GitHub Repository: nviennot/core-to-core-latency
Path: blob/main/src/bench.rs
228 views
1
pub mod cas;
2
pub mod read_write;
3
pub mod msg_passing;
4
5
use ansi_term::Color;
6
use core_affinity::CoreId;
7
use quanta::Clock;
8
use std::io::Write;
9
use ndarray::{s, Axis};
10
use ordered_float::NotNan;
11
use crate::CliArgs;
12
13
pub type Count = u32;
14
15
pub trait Bench {
16
fn run(&self, cores: (CoreId, CoreId), clock: &Clock, num_iterations: Count, num_samples: Count) -> Vec<f64>;
17
/// Whether the bench on (i,j) is the same as the bench on (j,i)
18
fn is_symmetric(&self) -> bool { true }
19
}
20
21
pub fn run_bench(cores: &[CoreId], clock: &Clock, args: &CliArgs, bench: impl Bench) {
22
let num_samples = args.num_samples;
23
let num_iterations = args.num_iterations;
24
25
let n_cores = cores.len();
26
assert!(n_cores >= 2);
27
let shape = ndarray::Ix3(n_cores, n_cores, num_samples as usize);
28
let mut results = ndarray::Array::from_elem(shape, f64::NAN);
29
30
// First print the column header
31
eprint!(" {: >3}", "");
32
for j in cores {
33
eprint!(" {: >4}{: >3}", j.id, "");
34
// |||
35
// ||+-- Width
36
// |+--- Align
37
// +---- Fill
38
}
39
eprintln!();
40
41
let mcolor = Color::White.bold();
42
let scolor = Color::White.dimmed();
43
44
// Do the benchmark
45
for i in 0..n_cores {
46
let core_i = cores[i];
47
eprint!(" {: >3}", core_i.id);
48
for j in 0..n_cores {
49
if bench.is_symmetric() {
50
if i <= j {
51
continue;
52
}
53
} else if i == j {
54
eprint!("{: >8}", "");
55
continue;
56
}
57
58
let core_j = cores[j];
59
// We add 1 warmup cycle first
60
let durations = bench.run((core_i, core_j), clock, num_iterations, 1+num_samples);
61
let durations = &durations[1..];
62
let mut values = results.slice_mut(s![i,j,..]);
63
for s in 0..num_samples as usize {
64
values[s] = durations[s]
65
}
66
67
let mean = format!("{: >4.0}", values.mean().unwrap());
68
// We apply the central limit theorem to estimate the standard deviation
69
let stddev = format!("±{: <2.0}", values.std(1.0).min(99.0) / (num_samples as f64).sqrt());
70
eprint!(" {}{}", mcolor.paint(mean), scolor.paint(stddev));
71
let _ = std::io::stdout().lock().flush();
72
}
73
eprintln!();
74
}
75
76
eprintln!();
77
78
// Print min/max latency
79
{
80
let mean = results.mean_axis(Axis(2)).unwrap();
81
let stddev = results.std_axis(Axis(2), 1.0) / (num_samples as f64).sqrt();
82
83
let ((min_i, min_j), _) = mean.indexed_iter()
84
.filter_map(|(i, v)| NotNan::new(*v).ok().map(|v| (i, v)))
85
.min_by_key(|(_, v)| *v)
86
.unwrap();
87
let min_mean = format!("{:.1}", mean[(min_i, min_j)]);
88
let min_stddev = format!("±{:.1}", stddev[(min_i, min_j)]);
89
let (min_core_id_i, min_core_id_j) = (cores[min_i].id, cores[min_j].id);
90
91
let ((max_i, max_j), _) = mean.indexed_iter()
92
.filter_map(|(i, v)| NotNan::new(*v).ok().map(|v| (i, v)))
93
.max_by_key(|(_, v)| *v)
94
.unwrap();
95
let max_mean = format!("{:.1}", mean[(max_i, max_j)]);
96
let max_stddev = format!("±{:.1}", stddev[(max_i, max_j)]);
97
let (max_core_id_i, max_core_id_j) = (cores[max_i].id, cores[max_j].id);
98
99
eprintln!(" Min latency: {}ns {} cores: ({},{})", mcolor.paint(min_mean), scolor.paint(min_stddev), min_core_id_i, min_core_id_j);
100
eprintln!(" Max latency: {}ns {} cores: ({},{})", mcolor.paint(max_mean), scolor.paint(max_stddev), max_core_id_i, max_core_id_j);
101
}
102
103
// Print mean latency
104
{
105
let values = results.iter().copied().filter(|v| !v.is_nan()).collect::<Vec<_>>();
106
let values = ndarray::arr1(&values);
107
let mean = format!("{:.1}", values.mean().unwrap());
108
// no stddev, it's hard to put a value that is meaningful without a lengthy explanation
109
eprintln!(" Mean latency: {}ns", mcolor.paint(mean));
110
}
111
112
if args.csv {
113
let results = results.mean_axis(Axis(2)).unwrap();
114
for row in results.rows() {
115
let row = row.iter()
116
.map(|v| if v.is_nan() { "".to_string() } else { v.to_string() })
117
.collect::<Vec<_>>().join(",");
118
println!("{}", row);
119
}
120
}
121
}
122
123