honeycomb_benches/
shift.rs

1//! `shift` benchmark
2//!
3//! The benchmark fetches all vertices that are not on the border of the map, fetch all identifiers
4//! of each respective vertices' neighbors. Then, for all vertices:
5//!
6//! - compute the average between neighbors,
7//! - overwrite current vertex value with computed average.
8//!
9//! This is done for a given number of rounds, to reach significant execution time and an accurate
10//! average.
11
12use honeycomb::kernels::remeshing::move_vertex_to_average;
13use rayon::prelude::*;
14
15use honeycomb::core::stm::{Transaction, TransactionControl};
16use honeycomb::prelude::{
17    CMap2, CMapBuilder, CoordsFloat, DartIdType, NULL_DART_ID, OrbitPolicy, VertexIdType,
18};
19
20use crate::cli::ShiftArgs;
21use crate::utils::hash_file;
22use crate::{prof_start, prof_stop};
23
24pub fn bench_shift<T: CoordsFloat>(args: ShiftArgs) -> CMap2<T> {
25    let mut instant = std::time::Instant::now();
26    let input_map = args.input.to_str().unwrap();
27    let input_hash = hash_file(input_map).unwrap();
28    let map: CMap2<T> = if input_map.ends_with(".cmap") {
29        CMapBuilder::<2, T>::from_cmap_file(input_map)
30            .build()
31            .unwrap()
32    } else if input_map.ends_with(".vtk") {
33        CMapBuilder::<2, T>::from_vtk_file(input_map)
34            .build()
35            .unwrap()
36    } else {
37        panic!(
38            "E: Unknown file format; only .cmap or .vtk files are supported for map initialization"
39        );
40    };
41    let build_time = instant.elapsed();
42
43    prof_start!("HCBENCH_SHIFT");
44    if args.no_conflict {
45        todo!("TODO: require a partitioning algorithm")
46    } else {
47        instant = std::time::Instant::now();
48        // fetch all vertices that are not on the boundary of the map
49        let tmp: Vec<(VertexIdType, Vec<VertexIdType>)> = map
50            .iter_vertices()
51            .filter_map(|v| {
52                if map
53                    .orbit(OrbitPolicy::Vertex, v as DartIdType)
54                    .any(|d| map.beta::<2>(d) == NULL_DART_ID)
55                {
56                    None
57                } else {
58                    Some((
59                        v,
60                        map.orbit(OrbitPolicy::Vertex, v as DartIdType)
61                            .map(|d| map.vertex_id(map.beta::<2>(d)))
62                            .collect(),
63                    ))
64                }
65            })
66            .collect();
67        let n_v = tmp.len();
68        let graph_time = instant.elapsed();
69        let n_threads = rayon::current_num_threads();
70
71        println!("| shift benchmark");
72        println!("|-> input      : {input_map} (hash: {input_hash:#0x})");
73        println!("|-> backend    : rayon-iter with {n_threads} thread(s)",);
74        println!("|-> # of rounds: {}", args.n_rounds.get());
75        println!("|-+ init time  :");
76        println!("| |->   map built in {}ms", build_time.as_millis());
77        println!("| |-> graph built in {}ms", graph_time.as_millis());
78
79        println!(" Round | process_time | throughput(vertex/s) | n_transac_retry");
80        // main loop
81        let mut round = 0;
82        let mut process_time;
83        loop {
84            instant = std::time::Instant::now();
85            let n_retry: u32 = tmp
86                .par_iter()
87                .map(|(vid, neigh)| {
88                    let mut n = 0;
89                    Transaction::with_control(
90                        |_| {
91                            n += 1;
92                            TransactionControl::Retry
93                        },
94                        |trans| move_vertex_to_average(trans, &map, *vid, neigh),
95                    );
96                    n
97                })
98                .sum();
99            process_time = instant.elapsed().as_secs_f64();
100            println!(
101                " {:>5} | {:>12.6e} | {:>20.6e} | {:>15}",
102                round,
103                process_time,
104                n_v as f64 / process_time,
105                n_retry,
106            );
107
108            round += 1;
109            if round >= args.n_rounds.get() {
110                break;
111            }
112        }
113    }
114    prof_stop!("HCBENCH_SHIFT");
115
116    map
117}