From 25c8d594c5b8445176c63cde7403a143402a9108 Mon Sep 17 00:00:00 2001 From: imrn99 <95699343+imrn99@users.noreply.github.com> Date: Mon, 28 Oct 2024 08:57:27 +0100 Subject: [PATCH 1/8] remove useless if / wrong range --- .../cmap/builder/grid/building_routines.rs | 176 +++++++++--------- 1 file changed, 86 insertions(+), 90 deletions(-) diff --git a/honeycomb-core/src/cmap/builder/grid/building_routines.rs b/honeycomb-core/src/cmap/builder/grid/building_routines.rs index 331ef0e66..46dabb5e9 100644 --- a/honeycomb-core/src/cmap/builder/grid/building_routines.rs +++ b/honeycomb-core/src/cmap/builder/grid/building_routines.rs @@ -40,59 +40,57 @@ pub fn build_2d_grid( }); // then cells - (0..=n_square_y).for_each(|y_idx| { - (0..=n_square_x).for_each(|x_idx| { + (0..n_square_y).for_each(|y_idx| { + (0..n_square_x).for_each(|x_idx| { // update the associated 0-cell - if (y_idx < n_square_y) & (x_idx < n_square_x) { - let base_dart = (1 + 4 * x_idx + n_square_x * 4 * y_idx) as DartIdentifier; - let vertex_id = map.vertex_id(base_dart); + let base_dart = (1 + 4 * x_idx + n_square_x * 4 * y_idx) as DartIdentifier; + let vertex_id = map.vertex_id(base_dart); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx).unwrap() * len_per_y, + ), + ); + let last_column = x_idx == n_square_x - 1; + let last_row = y_idx == n_square_y - 1; + if last_column { + // that last column of 0-cell needs special treatment + // bc there are no "horizontal" associated dart + let vertex_id = map.vertex_id(base_dart + 1); map.insert_vertex( vertex_id, origin + Vector2( - T::from(x_idx).unwrap() * len_per_x, + T::from(x_idx + 1).unwrap() * len_per_x, T::from(y_idx).unwrap() * len_per_y, ), ); - let last_column = x_idx == n_square_x - 1; - let last_row = y_idx == n_square_y - 1; - if last_column { - // that last column of 0-cell needs special treatment - // bc there are no "horizontal" associated dart - let vertex_id = map.vertex_id(base_dart + 1); - map.insert_vertex( - vertex_id, - origin - + Vector2( - T::from(x_idx + 1).unwrap() * len_per_x, - T::from(y_idx).unwrap() * len_per_y, - ), - ); - } - if last_row { - // same as the case on x - let vertex_id = map.vertex_id(base_dart + 3); - map.insert_vertex( - vertex_id, - origin - + Vector2( - T::from(x_idx).unwrap() * len_per_x, - T::from(y_idx + 1).unwrap() * len_per_y, - ), - ); - } - if last_row & last_column { - // need to do the upper right corner - let vertex_id = map.vertex_id(base_dart + 2); - map.insert_vertex( - vertex_id, - origin - + Vector2( - T::from(x_idx + 1).unwrap() * len_per_x, - T::from(y_idx + 1).unwrap() * len_per_y, - ), - ); - } + } + if last_row { + // same as the case on x + let vertex_id = map.vertex_id(base_dart + 3); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx + 1).unwrap() * len_per_y, + ), + ); + } + if last_row & last_column { + // need to do the upper right corner + let vertex_id = map.vertex_id(base_dart + 2); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx + 1).unwrap() * len_per_x, + T::from(y_idx + 1).unwrap() * len_per_y, + ), + ); } }); }); @@ -143,59 +141,57 @@ pub fn build_2d_splitgrid( }); // then cells - (0..=n_square_y).for_each(|y_idx| { - (0..=n_square_x).for_each(|x_idx| { + (0..n_square_y).for_each(|y_idx| { + (0..n_square_x).for_each(|x_idx| { // update the associated 0-cell - if (y_idx < n_square_y) & (x_idx < n_square_x) { - let base_dart = (1 + 6 * (x_idx + n_square_x * y_idx)) as DartIdentifier; - let vertex_id = map.vertex_id(base_dart); + let base_dart = (1 + 6 * (x_idx + n_square_x * y_idx)) as DartIdentifier; + let vertex_id = map.vertex_id(base_dart); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx).unwrap() * len_per_y, + ), + ); + let last_column = x_idx == n_square_x - 1; + let last_row = y_idx == n_square_y - 1; + if last_column { + // that last column of 0-cell needs special treatment + // bc there are no "horizontal" associated dart + let vertex_id = map.vertex_id(base_dart + 4); map.insert_vertex( vertex_id, origin + Vector2( - T::from(x_idx).unwrap() * len_per_x, + T::from(x_idx + 1).unwrap() * len_per_x, T::from(y_idx).unwrap() * len_per_y, ), ); - let last_column = x_idx == n_square_x - 1; - let last_row = y_idx == n_square_y - 1; - if last_column { - // that last column of 0-cell needs special treatment - // bc there are no "horizontal" associated dart - let vertex_id = map.vertex_id(base_dart + 4); - map.insert_vertex( - vertex_id, - origin - + Vector2( - T::from(x_idx + 1).unwrap() * len_per_x, - T::from(y_idx).unwrap() * len_per_y, - ), - ); - } - if last_row { - // same as the case on x - let vertex_id = map.vertex_id(base_dart + 2); - map.insert_vertex( - vertex_id, - origin - + Vector2( - T::from(x_idx).unwrap() * len_per_x, - T::from(y_idx + 1).unwrap() * len_per_y, - ), - ); - } - if last_row & last_column { - // need to do the upper right corner - let vertex_id = map.vertex_id(base_dart + 5); - map.insert_vertex( - vertex_id, - origin - + Vector2( - T::from(x_idx + 1).unwrap() * len_per_x, - T::from(y_idx + 1).unwrap() * len_per_y, - ), - ); - } + } + if last_row { + // same as the case on x + let vertex_id = map.vertex_id(base_dart + 2); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx + 1).unwrap() * len_per_y, + ), + ); + } + if last_row & last_column { + // need to do the upper right corner + let vertex_id = map.vertex_id(base_dart + 5); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx + 1).unwrap() * len_per_x, + T::from(y_idx + 1).unwrap() * len_per_y, + ), + ); } }); }); From 5df744dedfce2f0bc086db1bf9f842b2cb28b7ee Mon Sep 17 00:00:00 2001 From: imrn99 <95699343+imrn99@users.noreply.github.com> Date: Mon, 28 Oct 2024 08:59:18 +0100 Subject: [PATCH 2/8] fuse topology & geometry loops --- .../src/cmap/builder/grid/building_routines.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/honeycomb-core/src/cmap/builder/grid/building_routines.rs b/honeycomb-core/src/cmap/builder/grid/building_routines.rs index 46dabb5e9..0b6115a2a 100644 --- a/honeycomb-core/src/cmap/builder/grid/building_routines.rs +++ b/honeycomb-core/src/cmap/builder/grid/building_routines.rs @@ -36,12 +36,6 @@ pub fn build_2d_grid( let up_neighbor = d1 + (4 * n_square_x) as DartIdentifier; map.two_link(d3, up_neighbor); } - }); - }); - - // then cells - (0..n_square_y).for_each(|y_idx| { - (0..n_square_x).for_each(|x_idx| { // update the associated 0-cell let base_dart = (1 + 4 * x_idx + n_square_x * 4 * y_idx) as DartIdentifier; let vertex_id = map.vertex_id(base_dart); @@ -137,12 +131,7 @@ pub fn build_2d_splitgrid( let up_neighbor = d1 + (6 * n_square_x) as DartIdentifier; map.two_link(d6, up_neighbor); } - }); - }); - // then cells - (0..n_square_y).for_each(|y_idx| { - (0..n_square_x).for_each(|x_idx| { // update the associated 0-cell let base_dart = (1 + 6 * (x_idx + n_square_x * y_idx)) as DartIdentifier; let vertex_id = map.vertex_id(base_dart); From 7975fd58ee06c0b4495e5938cb8a464db935a535 Mon Sep 17 00:00:00 2001 From: imrn99 <95699343+imrn99@users.noreply.github.com> Date: Mon, 28 Oct 2024 09:03:51 +0100 Subject: [PATCH 3/8] flatten loop and remove redundant computations --- .../cmap/builder/grid/building_routines.rs | 119 +++++++++++------- 1 file changed, 74 insertions(+), 45 deletions(-) diff --git a/honeycomb-core/src/cmap/builder/grid/building_routines.rs b/honeycomb-core/src/cmap/builder/grid/building_routines.rs index 0b6115a2a..44ff04657 100644 --- a/honeycomb-core/src/cmap/builder/grid/building_routines.rs +++ b/honeycomb-core/src/cmap/builder/grid/building_routines.rs @@ -17,28 +17,44 @@ pub fn build_2d_grid( let mut map: CMap2 = CMap2::new_with_undefined_attributes(4 * n_square_x * n_square_y, manager); - // first, topology - (0..n_square_y).for_each(|y_idx| { - (0..n_square_x).for_each(|x_idx| { + (0..n_square_y) + .flat_map(|y_idx| (0..n_square_x).map(move |x_idx| (y_idx, x_idx))) + .for_each(|(y_idx, x_idx)| { + // compute dart IDs of the cell let d1 = (1 + 4 * x_idx + n_square_x * 4 * y_idx) as DartIdentifier; let (d2, d3, d4) = (d1 + 1, d1 + 2, d1 + 3); - map.one_link(d1, d2); - map.one_link(d2, d3); - map.one_link(d3, d4); - map.one_link(d4, d1); + // are we on the last col / row / both? + let last_column = x_idx == n_square_x - 1; + let last_row = y_idx == n_square_y - 1; + + // edit topology + // d1 + map.set_beta::<0>(d1, d4); + map.set_beta::<1>(d1, d2); + // d2 + map.set_beta::<0>(d2, d1); + map.set_beta::<1>(d2, d3); + // d3 + map.set_beta::<0>(d3, d2); + map.set_beta::<1>(d3, d4); + // d4 + map.set_beta::<0>(d4, d3); + map.set_beta::<1>(d4, d1); // if there is a right neighbor, sew sew - if x_idx != n_square_x - 1 { + if !last_column { let right_neighbor = d2 + 6; - map.two_link(d2, right_neighbor); + map.set_beta::<2>(d2, right_neighbor); + map.set_beta::<2>(right_neighbor, d2); } // if there is an up neighbor, sew sew - if y_idx != n_square_y - 1 { + if !last_row { let up_neighbor = d1 + (4 * n_square_x) as DartIdentifier; - map.two_link(d3, up_neighbor); + map.set_beta::<2>(d3, up_neighbor); + map.set_beta::<2>(up_neighbor, d3); } - // update the associated 0-cell - let base_dart = (1 + 4 * x_idx + n_square_x * 4 * y_idx) as DartIdentifier; - let vertex_id = map.vertex_id(base_dart); + + // edit geometry + let vertex_id = map.vertex_id(d1); map.insert_vertex( vertex_id, origin @@ -47,12 +63,10 @@ pub fn build_2d_grid( T::from(y_idx).unwrap() * len_per_y, ), ); - let last_column = x_idx == n_square_x - 1; - let last_row = y_idx == n_square_y - 1; if last_column { // that last column of 0-cell needs special treatment // bc there are no "horizontal" associated dart - let vertex_id = map.vertex_id(base_dart + 1); + let vertex_id = map.vertex_id(d2); map.insert_vertex( vertex_id, origin @@ -64,7 +78,7 @@ pub fn build_2d_grid( } if last_row { // same as the case on x - let vertex_id = map.vertex_id(base_dart + 3); + let vertex_id = map.vertex_id(d4); map.insert_vertex( vertex_id, origin @@ -76,7 +90,7 @@ pub fn build_2d_grid( } if last_row & last_column { // need to do the upper right corner - let vertex_id = map.vertex_id(base_dart + 2); + let vertex_id = map.vertex_id(d3); map.insert_vertex( vertex_id, origin @@ -87,7 +101,6 @@ pub fn build_2d_grid( ); } }); - }); // and then build faces assert_eq!(map.fetch_faces().identifiers.len(), n_square_x * n_square_y); @@ -105,36 +118,54 @@ pub fn build_2d_splitgrid( let mut map: CMap2 = CMap2::new_with_undefined_attributes(6 * n_square_x * n_square_y, manager); - // first, topology - (0..n_square_y).for_each(|y_idx| { - (0..n_square_x).for_each(|x_idx| { + (0..n_square_y) + .flat_map(|y_idx| (0..n_square_x).map(move |x_idx| (y_idx, x_idx))) + .for_each(|(y_idx, x_idx)| { + // compute dart IDs of the cell let d1 = (1 + 6 * (x_idx + n_square_x * y_idx)) as DartIdentifier; let (d2, d3, d4, d5, d6) = (d1 + 1, d1 + 2, d1 + 3, d1 + 4, d1 + 5); - // bottom left triangle - map.one_link(d1, d2); - map.one_link(d2, d3); - map.one_link(d3, d1); - // top right triangle - map.one_link(d4, d5); - map.one_link(d5, d6); - map.one_link(d6, d4); + // are we on the last col / row / both? + let last_column = x_idx == n_square_x - 1; + let last_row = y_idx == n_square_y - 1; + + // edit topology + // d1 + map.set_beta::<0>(d1, d3); + map.set_beta::<1>(d1, d2); + // d2 + map.set_beta::<0>(d2, d1); + map.set_beta::<1>(d2, d3); + // d3 + map.set_beta::<0>(d3, d2); + map.set_beta::<1>(d3, d1); + // d4 + map.set_beta::<0>(d4, d6); + map.set_beta::<1>(d4, d5); + // d5 + map.set_beta::<0>(d5, d4); + map.set_beta::<1>(d5, d6); + // d6 + map.set_beta::<0>(d6, d5); + map.set_beta::<1>(d6, d4); // diagonal - map.two_link(d2, d4); + map.set_beta::<2>(d2, d4); + map.set_beta::<2>(d4, d2); // if there is a right neighbor, sew sew - if x_idx != n_square_x - 1 { + if !last_column { let right_neighbor = d1 + 8; - map.two_link(d5, right_neighbor); + map.set_beta::<2>(d5, right_neighbor); + map.set_beta::<2>(right_neighbor, d5); } // if there is an up neighbor, sew sew - if y_idx != n_square_x - 1 { + if !last_row { let up_neighbor = d1 + (6 * n_square_x) as DartIdentifier; - map.two_link(d6, up_neighbor); + map.set_beta::<2>(d6, up_neighbor); + map.set_beta::<2>(up_neighbor, d6); } - // update the associated 0-cell - let base_dart = (1 + 6 * (x_idx + n_square_x * y_idx)) as DartIdentifier; - let vertex_id = map.vertex_id(base_dart); + // edit geometry + let vertex_id = map.vertex_id(d1); map.insert_vertex( vertex_id, origin @@ -143,12 +174,10 @@ pub fn build_2d_splitgrid( T::from(y_idx).unwrap() * len_per_y, ), ); - let last_column = x_idx == n_square_x - 1; - let last_row = y_idx == n_square_y - 1; if last_column { // that last column of 0-cell needs special treatment // bc there are no "horizontal" associated dart - let vertex_id = map.vertex_id(base_dart + 4); + let vertex_id = map.vertex_id(d5); map.insert_vertex( vertex_id, origin @@ -160,7 +189,7 @@ pub fn build_2d_splitgrid( } if last_row { // same as the case on x - let vertex_id = map.vertex_id(base_dart + 2); + let vertex_id = map.vertex_id(d3); map.insert_vertex( vertex_id, origin @@ -172,7 +201,7 @@ pub fn build_2d_splitgrid( } if last_row & last_column { // need to do the upper right corner - let vertex_id = map.vertex_id(base_dart + 5); + let vertex_id = map.vertex_id(d6); map.insert_vertex( vertex_id, origin @@ -183,7 +212,7 @@ pub fn build_2d_splitgrid( ); } }); - }); + // rebuild faces assert_eq!( map.fetch_faces().identifiers.len(), From 8e0050a905975535966512cafa8a31070352fab6 Mon Sep 17 00:00:00 2001 From: imrn99 <95699343+imrn99@users.noreply.github.com> Date: Mon, 28 Oct 2024 09:05:03 +0100 Subject: [PATCH 4/8] swap assertions to debug --- honeycomb-core/src/cmap/builder/grid/building_routines.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/honeycomb-core/src/cmap/builder/grid/building_routines.rs b/honeycomb-core/src/cmap/builder/grid/building_routines.rs index 44ff04657..9ae936793 100644 --- a/honeycomb-core/src/cmap/builder/grid/building_routines.rs +++ b/honeycomb-core/src/cmap/builder/grid/building_routines.rs @@ -103,7 +103,7 @@ pub fn build_2d_grid( }); // and then build faces - assert_eq!(map.fetch_faces().identifiers.len(), n_square_x * n_square_y); + debug_assert_eq!(map.fetch_faces().identifiers.len(), n_square_x * n_square_y); map } @@ -214,7 +214,7 @@ pub fn build_2d_splitgrid( }); // rebuild faces - assert_eq!( + debug_assert_eq!( map.fetch_faces().identifiers.len(), n_square_x * n_square_y * 2 ); From 5d61aa99170ba19920b1bd8d824648a2fc1d4df1 Mon Sep 17 00:00:00 2001 From: imrn99 <95699343+imrn99@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:44:00 +0100 Subject: [PATCH 5/8] address feedback --- .../src/cmap/builder/grid/building_routines.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/honeycomb-core/src/cmap/builder/grid/building_routines.rs b/honeycomb-core/src/cmap/builder/grid/building_routines.rs index 9ae936793..00a24484d 100644 --- a/honeycomb-core/src/cmap/builder/grid/building_routines.rs +++ b/honeycomb-core/src/cmap/builder/grid/building_routines.rs @@ -18,6 +18,8 @@ pub fn build_2d_grid( CMap2::new_with_undefined_attributes(4 * n_square_x * n_square_y, manager); (0..n_square_y) + // flatten the loop to expose more parallelism + // this is not a quantified/benchmarked upgrade, just a seemingly good change .flat_map(|y_idx| (0..n_square_x).map(move |x_idx| (y_idx, x_idx))) .for_each(|(y_idx, x_idx)| { // compute dart IDs of the cell @@ -102,7 +104,9 @@ pub fn build_2d_grid( } }); - // and then build faces + // check the number of built faces + // this is set as debug only because the operation cost scales with map size + // this can quickly overshadow the exectime of all previous code debug_assert_eq!(map.fetch_faces().identifiers.len(), n_square_x * n_square_y); map @@ -119,6 +123,8 @@ pub fn build_2d_splitgrid( CMap2::new_with_undefined_attributes(6 * n_square_x * n_square_y, manager); (0..n_square_y) + // flatten the loop to expose more parallelism + // this is not a quantified/benchmarked upgrade, just a seemingly good change .flat_map(|y_idx| (0..n_square_x).map(move |x_idx| (y_idx, x_idx))) .for_each(|(y_idx, x_idx)| { // compute dart IDs of the cell @@ -213,7 +219,9 @@ pub fn build_2d_splitgrid( } }); - // rebuild faces + // check the number of built faces + // this is set as debug only because the operation cost scales with map size + // this can quickly overshadow the exectime of all previous code debug_assert_eq!( map.fetch_faces().identifiers.len(), n_square_x * n_square_y * 2 From c69c6d01def65c53c19aa0ccbc90c03ee7e0cef5 Mon Sep 17 00:00:00 2001 From: imrn99 <95699343+imrn99@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:40:16 +0100 Subject: [PATCH 6/8] split last row/col cases from the grid building loop extract some function common to all cases --- benches/benches/builder/time.rs | 2 +- .../cmap/builder/grid/building_routines.rs | 237 ++++++++++++------ 2 files changed, 166 insertions(+), 73 deletions(-) diff --git a/benches/benches/builder/time.rs b/benches/benches/builder/time.rs index e2d21e489..f3a6384b4 100644 --- a/benches/benches/builder/time.rs +++ b/benches/benches/builder/time.rs @@ -13,7 +13,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { let mut group = c.benchmark_group("builder-time"); - let n_square = 128; + let n_square = 512; group.bench_with_input(BenchmarkId::new("unit-squares", ""), &(), |b, _| { b.iter(|| { diff --git a/honeycomb-core/src/cmap/builder/grid/building_routines.rs b/honeycomb-core/src/cmap/builder/grid/building_routines.rs index 00a24484d..e2b39529c 100644 --- a/honeycomb-core/src/cmap/builder/grid/building_routines.rs +++ b/honeycomb-core/src/cmap/builder/grid/building_routines.rs @@ -8,6 +8,7 @@ use crate::{attributes::AttrStorageManager, geometry::CoordsFloat}; // ------ CONTENT /// Internal grid-building routine +#[allow(clippy::too_many_lines)] pub fn build_2d_grid( origin: Vertex2, [n_square_x, n_square_y]: [usize; 2], @@ -17,46 +18,20 @@ pub fn build_2d_grid( let mut map: CMap2 = CMap2::new_with_undefined_attributes(4 * n_square_x * n_square_y, manager); - (0..n_square_y) + // regular iterations (skip last row/col) + (0..n_square_y - 1) // flatten the loop to expose more parallelism - // this is not a quantified/benchmarked upgrade, just a seemingly good change - .flat_map(|y_idx| (0..n_square_x).map(move |x_idx| (y_idx, x_idx))) + .flat_map(|y_idx| (0..n_square_x - 1).map(move |x_idx| (y_idx, x_idx))) .for_each(|(y_idx, x_idx)| { - // compute dart IDs of the cell - let d1 = (1 + 4 * x_idx + n_square_x * 4 * y_idx) as DartIdentifier; - let (d2, d3, d4) = (d1 + 1, d1 + 2, d1 + 3); - // are we on the last col / row / both? - let last_column = x_idx == n_square_x - 1; - let last_row = y_idx == n_square_y - 1; + // build basic topology & fetch dart IDs of the cell + let [d1, d2, d3, _] = build_square_core(&mut map, n_square_x, [x_idx, y_idx]); - // edit topology - // d1 - map.set_beta::<0>(d1, d4); - map.set_beta::<1>(d1, d2); - // d2 - map.set_beta::<0>(d2, d1); - map.set_beta::<1>(d2, d3); - // d3 - map.set_beta::<0>(d3, d2); - map.set_beta::<1>(d3, d4); - // d4 - map.set_beta::<0>(d4, d3); - map.set_beta::<1>(d4, d1); - // if there is a right neighbor, sew sew - if !last_column { - let right_neighbor = d2 + 6; - map.set_beta::<2>(d2, right_neighbor); - map.set_beta::<2>(right_neighbor, d2); - } - // if there is an up neighbor, sew sew - if !last_row { - let up_neighbor = d1 + (4 * n_square_x) as DartIdentifier; - map.set_beta::<2>(d3, up_neighbor); - map.set_beta::<2>(up_neighbor, d3); - } + // sew to right & up neighbors + build_square_sew_right(&mut map, d2); + build_square_sew_up(&mut map, d3, n_square_x); // edit geometry - let vertex_id = map.vertex_id(d1); + let vertex_id = map.vertex_id(d1); // bottom left map.insert_vertex( vertex_id, origin @@ -65,45 +40,116 @@ pub fn build_2d_grid( T::from(y_idx).unwrap() * len_per_y, ), ); - if last_column { - // that last column of 0-cell needs special treatment - // bc there are no "horizontal" associated dart - let vertex_id = map.vertex_id(d2); - map.insert_vertex( - vertex_id, - origin - + Vector2( - T::from(x_idx + 1).unwrap() * len_per_x, - T::from(y_idx).unwrap() * len_per_y, - ), - ); - } - if last_row { - // same as the case on x - let vertex_id = map.vertex_id(d4); - map.insert_vertex( - vertex_id, - origin - + Vector2( - T::from(x_idx).unwrap() * len_per_x, - T::from(y_idx + 1).unwrap() * len_per_y, - ), - ); - } - if last_row & last_column { - // need to do the upper right corner - let vertex_id = map.vertex_id(d3); - map.insert_vertex( - vertex_id, - origin - + Vector2( - T::from(x_idx + 1).unwrap() * len_per_x, - T::from(y_idx + 1).unwrap() * len_per_y, - ), - ); - } }); + // last row (except top right square) + (0..n_square_x - 1).for_each(|x_idx| { + let y_idx = n_square_y - 1; + + // build basic topology & fetch dart IDs of the cell + let [d1, d2, _, d4] = build_square_core(&mut map, n_square_x, [x_idx, y_idx]); + + // sew to right neighbor only + build_square_sew_right(&mut map, d2); + + // edit geometry + let vertex_id = map.vertex_id(d1); // bottom left + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx).unwrap() * len_per_y, + ), + ); + let vertex_id = map.vertex_id(d4); // top left + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx + 1).unwrap() * len_per_y, + ), + ); + }); + + // last col (except top right square) + (0..n_square_y - 1).for_each(|y_idx| { + let x_idx = n_square_x - 1; + + // build basic topology & fetch dart IDs of the cell + let [d1, d2, d3, _] = build_square_core(&mut map, n_square_x, [x_idx, y_idx]); + + // sew to up neighbor only + build_square_sew_up(&mut map, d3, n_square_x); + + // edit geometry + let vertex_id = map.vertex_id(d1); // bottom left + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx).unwrap() * len_per_y, + ), + ); + let vertex_id = map.vertex_id(d2); // bottom right + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx + 1).unwrap() * len_per_x, + T::from(y_idx).unwrap() * len_per_y, + ), + ); + }); + + // most top right cell + { + let (x_idx, y_idx) = (n_square_x - 1, n_square_y - 1); + + // build basic topology & fetch dart IDs of the cell + let [d1, d2, d3, d4] = build_square_core(&mut map, n_square_x, [x_idx, y_idx]); + + // edit geometry + let vertex_id = map.vertex_id(d1); // bottom left + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx).unwrap() * len_per_y, + ), + ); + let vertex_id = map.vertex_id(d2); // bottom right + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx + 1).unwrap() * len_per_x, + T::from(y_idx).unwrap() * len_per_y, + ), + ); + let vertex_id = map.vertex_id(d4); // top left + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx + 1).unwrap() * len_per_y, + ), + ); + let vertex_id = map.vertex_id(d3); // top right + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx + 1).unwrap() * len_per_x, + T::from(y_idx + 1).unwrap() * len_per_y, + ), + ); + } + // check the number of built faces // this is set as debug only because the operation cost scales with map size // this can quickly overshadow the exectime of all previous code @@ -112,6 +158,53 @@ pub fn build_2d_grid( map } +#[allow(clippy::inline_always)] +#[inline(always)] // seems like this is required to match the actual inline perf +fn build_square_core( + map: &mut CMap2, + n_square_x: usize, + [x_idx, y_idx]: [usize; 2], +) -> [DartIdentifier; 4] { + let d1 = (1 + 4 * x_idx + n_square_x * 4 * y_idx) as DartIdentifier; + let (d2, d3, d4) = (d1 + 1, d1 + 2, d1 + 3); + + // edit topology + // d1 + map.set_beta::<0>(d1, d4); + map.set_beta::<1>(d1, d2); + // d2 + map.set_beta::<0>(d2, d1); + map.set_beta::<1>(d2, d3); + // d3 + map.set_beta::<0>(d3, d2); + map.set_beta::<1>(d3, d4); + // d4 + map.set_beta::<0>(d4, d3); + map.set_beta::<1>(d4, d1); + + [d1, d2, d3, d4] +} + +#[allow(clippy::inline_always)] +#[inline(always)] // seems like this is required to match the actual inline perf +fn build_square_sew_right(map: &mut CMap2, dart: DartIdentifier) { + let right_neighbor = dart + 6; + map.set_beta::<2>(dart, right_neighbor); + map.set_beta::<2>(right_neighbor, dart); +} + +#[allow(clippy::inline_always)] +#[inline(always)] // seems like this is required to match the actual inline perf +fn build_square_sew_up( + map: &mut CMap2, + dart: DartIdentifier, + n_square_x: usize, +) { + let up_neighbor = dart - 2 + 4 * n_square_x as DartIdentifier; // d1 + 4*nx + map.set_beta::<2>(dart, up_neighbor); + map.set_beta::<2>(up_neighbor, dart); +} + /// Internal grid-building routine pub fn build_2d_splitgrid( origin: Vertex2, From c76472febfd160128e80fed3ddf61e38a5e9b335 Mon Sep 17 00:00:00 2001 From: imrn99 <95699343+imrn99@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:56:33 +0100 Subject: [PATCH 7/8] repeat for split grid routine --- .../cmap/builder/grid/building_routines.rs | 244 ++++++++++++------ 1 file changed, 166 insertions(+), 78 deletions(-) diff --git a/honeycomb-core/src/cmap/builder/grid/building_routines.rs b/honeycomb-core/src/cmap/builder/grid/building_routines.rs index e2b39529c..a57fba20b 100644 --- a/honeycomb-core/src/cmap/builder/grid/building_routines.rs +++ b/honeycomb-core/src/cmap/builder/grid/building_routines.rs @@ -206,6 +206,7 @@ fn build_square_sew_up( } /// Internal grid-building routine +#[allow(clippy::too_many_lines)] pub fn build_2d_splitgrid( origin: Vertex2, [n_square_x, n_square_y]: [usize; 2], @@ -215,53 +216,18 @@ pub fn build_2d_splitgrid( let mut map: CMap2 = CMap2::new_with_undefined_attributes(6 * n_square_x * n_square_y, manager); - (0..n_square_y) + (0..n_square_y - 1) // flatten the loop to expose more parallelism // this is not a quantified/benchmarked upgrade, just a seemingly good change - .flat_map(|y_idx| (0..n_square_x).map(move |x_idx| (y_idx, x_idx))) + .flat_map(|y_idx| (0..n_square_x - 1).map(move |x_idx| (y_idx, x_idx))) .for_each(|(y_idx, x_idx)| { - // compute dart IDs of the cell - let d1 = (1 + 6 * (x_idx + n_square_x * y_idx)) as DartIdentifier; - let (d2, d3, d4, d5, d6) = (d1 + 1, d1 + 2, d1 + 3, d1 + 4, d1 + 5); - // are we on the last col / row / both? - let last_column = x_idx == n_square_x - 1; - let last_row = y_idx == n_square_y - 1; - - // edit topology - // d1 - map.set_beta::<0>(d1, d3); - map.set_beta::<1>(d1, d2); - // d2 - map.set_beta::<0>(d2, d1); - map.set_beta::<1>(d2, d3); - // d3 - map.set_beta::<0>(d3, d2); - map.set_beta::<1>(d3, d1); - // d4 - map.set_beta::<0>(d4, d6); - map.set_beta::<1>(d4, d5); - // d5 - map.set_beta::<0>(d5, d4); - map.set_beta::<1>(d5, d6); - // d6 - map.set_beta::<0>(d6, d5); - map.set_beta::<1>(d6, d4); - // diagonal - map.set_beta::<2>(d2, d4); - map.set_beta::<2>(d4, d2); + // build basic topology & fetch dart IDs of the cell + let [d1, _, _, _, d5, d6] = build_tris_core(&mut map, n_square_x, [x_idx, y_idx]); // if there is a right neighbor, sew sew - if !last_column { - let right_neighbor = d1 + 8; - map.set_beta::<2>(d5, right_neighbor); - map.set_beta::<2>(right_neighbor, d5); - } + build_tris_sew_right(&mut map, d5); // if there is an up neighbor, sew sew - if !last_row { - let up_neighbor = d1 + (6 * n_square_x) as DartIdentifier; - map.set_beta::<2>(d6, up_neighbor); - map.set_beta::<2>(up_neighbor, d6); - } + build_tris_sew_up(&mut map, d6, n_square_x); // edit geometry let vertex_id = map.vertex_id(d1); @@ -273,45 +239,115 @@ pub fn build_2d_splitgrid( T::from(y_idx).unwrap() * len_per_y, ), ); - if last_column { - // that last column of 0-cell needs special treatment - // bc there are no "horizontal" associated dart - let vertex_id = map.vertex_id(d5); - map.insert_vertex( - vertex_id, - origin - + Vector2( - T::from(x_idx + 1).unwrap() * len_per_x, - T::from(y_idx).unwrap() * len_per_y, - ), - ); - } - if last_row { - // same as the case on x - let vertex_id = map.vertex_id(d3); - map.insert_vertex( - vertex_id, - origin - + Vector2( - T::from(x_idx).unwrap() * len_per_x, - T::from(y_idx + 1).unwrap() * len_per_y, - ), - ); - } - if last_row & last_column { - // need to do the upper right corner - let vertex_id = map.vertex_id(d6); - map.insert_vertex( - vertex_id, - origin - + Vector2( - T::from(x_idx + 1).unwrap() * len_per_x, - T::from(y_idx + 1).unwrap() * len_per_y, - ), - ); - } }); + // last row (except top right square) + (0..n_square_x - 1).for_each(|x_idx| { + let y_idx = n_square_y - 1; + + // build basic topology & fetch dart IDs of the cell + let [d1, _, d3, _, d5, _] = build_tris_core(&mut map, n_square_x, [x_idx, y_idx]); + + // sew right neighbor + build_tris_sew_right(&mut map, d5); + + // edit geometry + let vertex_id = map.vertex_id(d1); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx).unwrap() * len_per_y, + ), + ); + let vertex_id = map.vertex_id(d3); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx + 1).unwrap() * len_per_y, + ), + ); + }); + + // last col (except top right square) + (0..n_square_y - 1).for_each(|y_idx| { + let x_idx = n_square_x - 1; + + // build basic topology & fetch dart IDs of the cell + let [d1, _, _, _, d5, d6] = build_tris_core(&mut map, n_square_x, [x_idx, y_idx]); + + // sew up neighbor + build_tris_sew_up(&mut map, d6, n_square_x); + + // edit geometry + let vertex_id = map.vertex_id(d1); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx).unwrap() * len_per_y, + ), + ); + let vertex_id = map.vertex_id(d5); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx + 1).unwrap() * len_per_x, + T::from(y_idx).unwrap() * len_per_y, + ), + ); + }); + + // most top right cell + { + let (x_idx, y_idx) = (n_square_x - 1, n_square_y - 1); + + // build basic topology & fetch dart IDs of the cell + let [d1, _, d3, _, d5, d6] = build_tris_core(&mut map, n_square_x, [x_idx, y_idx]); + + let vertex_id = map.vertex_id(d1); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx).unwrap() * len_per_y, + ), + ); + let vertex_id = map.vertex_id(d3); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx).unwrap() * len_per_x, + T::from(y_idx + 1).unwrap() * len_per_y, + ), + ); + let vertex_id = map.vertex_id(d5); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx + 1).unwrap() * len_per_x, + T::from(y_idx).unwrap() * len_per_y, + ), + ); + let vertex_id = map.vertex_id(d6); + map.insert_vertex( + vertex_id, + origin + + Vector2( + T::from(x_idx + 1).unwrap() * len_per_x, + T::from(y_idx + 1).unwrap() * len_per_y, + ), + ); + } + // check the number of built faces // this is set as debug only because the operation cost scales with map size // this can quickly overshadow the exectime of all previous code @@ -322,3 +358,55 @@ pub fn build_2d_splitgrid( map } + +#[allow(clippy::inline_always)] +#[inline(always)] // seems like this is required to match the actual inline perf +fn build_tris_core( + map: &mut CMap2, + n_square_x: usize, + [x_idx, y_idx]: [usize; 2], +) -> [DartIdentifier; 6] { + let d1 = (1 + 6 * (x_idx + n_square_x * y_idx)) as DartIdentifier; + let (d2, d3, d4, d5, d6) = (d1 + 1, d1 + 2, d1 + 3, d1 + 4, d1 + 5); + + // edit topology + // d1 + map.set_beta::<0>(d1, d3); + map.set_beta::<1>(d1, d2); + // d2 + map.set_beta::<0>(d2, d1); + map.set_beta::<1>(d2, d3); + // d3 + map.set_beta::<0>(d3, d2); + map.set_beta::<1>(d3, d1); + // d4 + map.set_beta::<0>(d4, d6); + map.set_beta::<1>(d4, d5); + // d5 + map.set_beta::<0>(d5, d4); + map.set_beta::<1>(d5, d6); + // d6 + map.set_beta::<0>(d6, d5); + map.set_beta::<1>(d6, d4); + // diagonal + map.set_beta::<2>(d2, d4); + map.set_beta::<2>(d4, d2); + + [d1, d2, d3, d4, d5, d6] +} + +#[allow(clippy::inline_always)] +#[inline(always)] // seems like this is required to match the actual inline perf +fn build_tris_sew_right(map: &mut CMap2, dart: DartIdentifier) { + let right_neighbor = dart + 4; + map.set_beta::<2>(dart, right_neighbor); + map.set_beta::<2>(right_neighbor, dart); +} + +#[allow(clippy::inline_always)] +#[inline(always)] // seems like this is required to match the actual inline perf +fn build_tris_sew_up(map: &mut CMap2, dart: DartIdentifier, n_square_x: usize) { + let up_neighbor = dart - 5 + 6 * n_square_x as DartIdentifier; // d1 + 6*nx + map.set_beta::<2>(dart, up_neighbor); + map.set_beta::<2>(up_neighbor, dart); +} From fad1ca0b6c2b169596c58dcf3debdb6880398d3b Mon Sep 17 00:00:00 2001 From: imrn99 <95699343+imrn99@users.noreply.github.com> Date: Mon, 28 Oct 2024 15:58:35 +0100 Subject: [PATCH 8/8] revert bench to og size --- benches/benches/builder/time.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benches/benches/builder/time.rs b/benches/benches/builder/time.rs index f3a6384b4..e2d21e489 100644 --- a/benches/benches/builder/time.rs +++ b/benches/benches/builder/time.rs @@ -13,7 +13,7 @@ pub fn criterion_benchmark(c: &mut Criterion) { let mut group = c.benchmark_group("builder-time"); - let n_square = 512; + let n_square = 128; group.bench_with_input(BenchmarkId::new("unit-squares", ""), &(), |b, _| { b.iter(|| {