Skip to content

Commit cfe76fd

Browse files
committed
feat(apps): add subcommands for Laplace and Taubin smoothing in shift-vertices binary
1 parent 9f5053e commit cfe76fd

File tree

3 files changed

+145
-5
lines changed

3 files changed

+145
-5
lines changed

applications/shift_vertices/cli.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{num::NonZero, path::PathBuf};
22

3-
use clap::Parser;
3+
use clap::{Parser, Subcommand};
44

55
use applications::FileFormat;
66

@@ -22,4 +22,25 @@ pub struct Cli {
2222
/// Execute benchmarks using `f32` instead of the default `f64`
2323
#[arg(long("simple-precision"))]
2424
pub simple_precision: bool,
25+
#[command(subcommand)]
26+
pub command: Option<SmoothingType>,
27+
}
28+
29+
#[derive(Subcommand)]
30+
pub enum SmoothingType {
31+
/// Laplace smoothing
32+
Laplace {
33+
/// Scale coefficient
34+
#[arg(long, default_value_t = 0.5)]
35+
lambda: f64,
36+
},
37+
/// Taubin smoothing
38+
Taubin {
39+
/// Scale coefficient
40+
#[arg(long, default_value_t = 0.6307)]
41+
lambda: f64,
42+
/// Pass-band parameter
43+
#[arg(short, long("pass-band"), default_value_t = 0.1)]
44+
k: f64,
45+
},
2546
}

applications/shift_vertices/internals.rs

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use honeycomb::{
22
prelude::{
33
CMap2, CoordsFloat, DartIdType, NULL_DART_ID, OrbitPolicy, VertexIdType,
4-
remeshing::move_vertex_to_average,
4+
remeshing::{move_vertex_to_average, neighbor_based_smooth},
55
},
66
stm::atomically,
77
};
@@ -68,3 +68,70 @@ pub fn shift<T: CoordsFloat>(
6868
}
6969
}
7070
}
71+
72+
pub fn laplace<T: CoordsFloat>(
73+
map: &CMap2<T>,
74+
graph: &[(VertexIdType, Vec<VertexIdType>)],
75+
n_rounds: usize,
76+
lambda: T,
77+
) {
78+
println!(" Round | process_time | throughput(vertex/s)");
79+
// main loop
80+
let mut round = 0;
81+
let mut process_time;
82+
let n_v = graph.len();
83+
loop {
84+
let instant = std::time::Instant::now();
85+
graph.par_iter().for_each(|(vid, neigh)| {
86+
atomically(|t| neighbor_based_smooth(t, map, *vid, neigh, lambda));
87+
});
88+
process_time = instant.elapsed().as_secs_f64();
89+
println!(
90+
" {:>5} | {:>12.6e} | {:>20.6e}",
91+
round,
92+
process_time,
93+
n_v as f64 / process_time,
94+
);
95+
96+
round += 1;
97+
if round >= n_rounds {
98+
break;
99+
}
100+
}
101+
}
102+
103+
pub fn taubin<T: CoordsFloat>(
104+
map: &CMap2<T>,
105+
graph: &[(VertexIdType, Vec<VertexIdType>)],
106+
n_rounds: usize,
107+
lambda: T,
108+
k: T,
109+
) {
110+
println!(" Round | process_time | throughput(vertex/s)");
111+
// main loop
112+
let mut round = 0;
113+
let mut process_time;
114+
let n_v = graph.len();
115+
116+
let mu = T::one() / (k - T::one() / lambda);
117+
118+
loop {
119+
let instant = std::time::Instant::now();
120+
let scale = if round % 2 == 0 { lambda } else { mu };
121+
graph.par_iter().for_each(|(vid, neigh)| {
122+
atomically(|t| neighbor_based_smooth(t, map, *vid, neigh, scale));
123+
});
124+
process_time = instant.elapsed().as_secs_f64();
125+
println!(
126+
" {:>5} | {:>12.6e} | {:>20.6e}",
127+
round,
128+
process_time,
129+
n_v as f64 / process_time,
130+
);
131+
132+
round += 1;
133+
if round >= n_rounds {
134+
break;
135+
}
136+
}
137+
}

applications/shift_vertices/main.rs

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,21 @@ fn main() {
1717
let cli = cli::Cli::parse();
1818

1919
if cli.simple_precision {
20-
run_bench::<f32>(cli.input, cli.n_rounds.get(), cli.sort, cli.save_as);
20+
run_bench::<f32>(
21+
cli.input,
22+
cli.n_rounds.get(),
23+
cli.sort,
24+
cli.save_as,
25+
cli.command,
26+
);
2127
} else {
22-
run_bench::<f64>(cli.input, cli.n_rounds.get(), cli.sort, cli.save_as);
28+
run_bench::<f64>(
29+
cli.input,
30+
cli.n_rounds.get(),
31+
cli.sort,
32+
cli.save_as,
33+
cli.command,
34+
);
2335
}
2436
}
2537

@@ -28,6 +40,7 @@ fn run_bench<T: CoordsFloat>(
2840
n_rounds: usize,
2941
sort: bool,
3042
save: Option<FileFormat>,
43+
smoothing: Option<cli::SmoothingType>,
3144
) {
3245
let (map, input_hash, init_time) = init_2d_map_from_file::<T>(input.clone());
3346

@@ -41,12 +54,51 @@ fn run_bench<T: CoordsFloat>(
4154
get_num_threads().unwrap_or(1)
4255
);
4356
println!("|-> # of rounds: {}", n_rounds);
57+
58+
match smoothing {
59+
None => {
60+
println!("|-> smoothing : neighbor average",);
61+
}
62+
Some(cli::SmoothingType::Laplace { lambda }) => {
63+
println!("|-> smoothing : Laplace");
64+
println!("|-> scale (λ) : {}", lambda);
65+
assert!(
66+
lambda > 0.0 && lambda < 1.0,
67+
"lambda must verify `0 < lambda < 1`"
68+
);
69+
}
70+
Some(cli::SmoothingType::Taubin { lambda, k }) => {
71+
println!("|-> smoothing : Taubin");
72+
println!("|-> scale (λ) : {lambda}");
73+
println!("|-> pass (k) : {k}");
74+
assert!(
75+
lambda > 0.0 && lambda < 1.0,
76+
"lambda must verify `0 < lambda < 1`"
77+
);
78+
}
79+
}
4480
println!("|-+ init time :");
4581
println!("| |-> map built in {}ms", init_time.as_millis());
4682

4783
prof_start!("HCBENCH_SHIFT");
4884
let graph = internals::build_vertex_graph(&map, sort);
49-
internals::shift(&map, &graph, n_rounds);
85+
match smoothing {
86+
None => {
87+
internals::shift(&map, &graph, n_rounds);
88+
}
89+
Some(cli::SmoothingType::Laplace { lambda }) => {
90+
internals::laplace(&map, &graph, n_rounds, T::from(lambda).unwrap());
91+
}
92+
Some(cli::SmoothingType::Taubin { lambda, k }) => {
93+
internals::taubin(
94+
&map,
95+
&graph,
96+
n_rounds,
97+
T::from(lambda).unwrap(),
98+
T::from(k).unwrap(),
99+
);
100+
}
101+
}
50102
prof_stop!("HCBENCH_SHIFT");
51103

52104
finalize_2d(map, save);

0 commit comments

Comments
 (0)