Skip to content

Commit 3114b42

Browse files
authored
perf: wave 3 follow-up improvements (#21)
* ci(perf): add diffgeo coverage to smoke and deep reports * perf(dec): specialize curvature traversal for DEC storage * docs(perf): record continuation profiler pass
1 parent e0e8e9f commit 3114b42

6 files changed

Lines changed: 472 additions & 3 deletions

File tree

.github/workflows/perf-deep.yml

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
-DCMAKE_BUILD_TYPE=Release \
5656
-DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake \
5757
-DVCPKG_TARGET_TRIPLET=x64-linux
58-
cmake --build build-release --parallel --target bench_geometry bench_dod bench_pipelines
58+
cmake --build build-release --parallel --target bench_geometry bench_dod bench_pipelines bench_diffgeo
5959
6060
- name: Run head deep benchmarks
6161
shell: bash
@@ -78,6 +78,13 @@ jobs:
7878
--benchmark_out=artifacts/perf/head/bench_pipelines_head.json \
7979
--benchmark_out_format=json > artifacts/perf/head/bench_pipelines_head.txt
8080
81+
./build-release/bench_diffgeo \
82+
--benchmark_min_time=0.2s \
83+
--benchmark_repetitions=10 \
84+
--benchmark_report_aggregates_only=true \
85+
--benchmark_out=artifacts/perf/head/bench_diffgeo_head.json \
86+
--benchmark_out_format=json > artifacts/perf/head/bench_diffgeo_head.txt
87+
8188
- name: Build and run baseline deep benchmarks
8289
shell: bash
8390
run: |
@@ -114,6 +121,17 @@ jobs:
114121
echo "bench_pipelines target not available on baseline $BASELINE_SHA" > artifacts/perf/base/bench_pipelines_base.txt
115122
fi
116123
124+
if cmake --build baseline/build-release --parallel --target bench_diffgeo; then
125+
./baseline/build-release/bench_diffgeo \
126+
--benchmark_min_time=0.2s \
127+
--benchmark_repetitions=10 \
128+
--benchmark_report_aggregates_only=true \
129+
--benchmark_out=artifacts/perf/base/bench_diffgeo_base.json \
130+
--benchmark_out_format=json > artifacts/perf/base/bench_diffgeo_base.txt
131+
else
132+
echo "bench_diffgeo target not available on baseline $BASELINE_SHA" > artifacts/perf/base/bench_diffgeo_base.txt
133+
fi
134+
117135
- name: Compare benchmark deltas
118136
shell: bash
119137
run: |
@@ -141,6 +159,24 @@ jobs:
141159
--output-markdown artifacts/perf/reports/bench_pipelines_deep.md \
142160
--output-json artifacts/perf/reports/bench_pipelines_deep.json
143161
162+
if [[ -s artifacts/perf/base/bench_diffgeo_base.json ]]; then
163+
python3 scripts/perf/compare_against_main.py \
164+
--baseline artifacts/perf/base/bench_diffgeo_base.json \
165+
--current artifacts/perf/head/bench_diffgeo_head.json \
166+
--baseline-commit "$BASELINE_SHA" \
167+
--label "Deep run: bench_diffgeo (baseline $BASELINE_SHA)" \
168+
--output-markdown artifacts/perf/reports/bench_diffgeo_deep.md \
169+
--output-json artifacts/perf/reports/bench_diffgeo_deep.json
170+
else
171+
python3 scripts/perf/compare_against_main.py \
172+
--baseline artifacts/perf/base/bench_diffgeo_base.txt \
173+
--current artifacts/perf/head/bench_diffgeo_head.json \
174+
--baseline-commit "$BASELINE_SHA" \
175+
--label "Deep run: bench_diffgeo (baseline $BASELINE_SHA)" \
176+
--output-markdown artifacts/perf/reports/bench_diffgeo_deep.md \
177+
--output-json artifacts/perf/reports/bench_diffgeo_deep.json
178+
fi
179+
144180
{
145181
echo "# Perf Deep Report"
146182
echo
@@ -151,6 +187,8 @@ jobs:
151187
cat artifacts/perf/reports/bench_dod_deep.md
152188
echo
153189
cat artifacts/perf/reports/bench_pipelines_deep.md
190+
echo
191+
cat artifacts/perf/reports/bench_diffgeo_deep.md
154192
} > artifacts/perf/reports/deep-summary.md
155193
156194
- name: Build compact CSV summary
@@ -162,7 +200,7 @@ jobs:
162200
163201
out = Path("artifacts/perf/reports/deep-summary.csv")
164202
rows = ["suite,benchmark,baseline_ns,current_ns,delta_pct,status"]
165-
for suite in ("bench_geometry_deep", "bench_dod_deep", "bench_pipelines_deep"):
203+
for suite in ("bench_geometry_deep", "bench_dod_deep", "bench_pipelines_deep", "bench_diffgeo_deep"):
166204
path = Path(f"artifacts/perf/reports/{suite}.json")
167205
if not path.exists():
168206
continue

.github/workflows/perf-smoke.yml

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ jobs:
9292
-DCMAKE_BUILD_TYPE=Release \
9393
-DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake \
9494
-DVCPKG_TARGET_TRIPLET=x64-linux
95-
cmake --build build-release --parallel --target bench_geometry bench_dod bench_pipelines
95+
cmake --build build-release --parallel --target bench_geometry bench_dod bench_pipelines bench_diffgeo
9696
9797
- name: Run head smoke benchmarks
9898
shell: bash
@@ -117,6 +117,14 @@ jobs:
117117
--benchmark_out=artifacts/perf/head/bench_pipelines_head.json \
118118
--benchmark_out_format=json > artifacts/perf/head/bench_pipelines_head.txt
119119
120+
./build-release/bench_diffgeo \
121+
--benchmark_filter='bench_diffgeo_pipeline/1000/50/32/32|bench_diffgeo_pipeline/4000/64/32/32|bench_diffgeo_phase_structure_build/1000/50/32/32|bench_diffgeo_phase_structure_build/4000/64/32/32|bench_diffgeo_phase_eigenbasis/1000/50/32/32|bench_diffgeo_phase_eigenbasis/4000/64/32/32|bench_diffgeo_phase_circular/1000/50/32/32|bench_diffgeo_phase_circular/4000/64/32/32|bench_diffgeo_phase_k1_up/4000/64/32/32|bench_diffgeo_phase_k2_up/4000/64/32/32' \
122+
--benchmark_min_time=0.05s \
123+
--benchmark_repetitions=5 \
124+
--benchmark_report_aggregates_only=true \
125+
--benchmark_out=artifacts/perf/head/bench_diffgeo_head.json \
126+
--benchmark_out_format=json > artifacts/perf/head/bench_diffgeo_head.txt
127+
120128
- name: Build and run baseline smoke benchmarks
121129
shell: bash
122130
run: |
@@ -155,6 +163,18 @@ jobs:
155163
echo "bench_pipelines target not available on baseline ${{ steps.baseline.outputs.base_sha }}" > artifacts/perf/base/bench_pipelines_base.txt
156164
fi
157165
166+
if cmake --build baseline/build-release --parallel --target bench_diffgeo; then
167+
./baseline/build-release/bench_diffgeo \
168+
--benchmark_filter='bench_diffgeo_pipeline/1000/50/32/32|bench_diffgeo_pipeline/4000/64/32/32|bench_diffgeo_phase_structure_build/1000/50/32/32|bench_diffgeo_phase_structure_build/4000/64/32/32|bench_diffgeo_phase_eigenbasis/1000/50/32/32|bench_diffgeo_phase_eigenbasis/4000/64/32/32|bench_diffgeo_phase_circular/1000/50/32/32|bench_diffgeo_phase_circular/4000/64/32/32|bench_diffgeo_phase_k1_up/4000/64/32/32|bench_diffgeo_phase_k2_up/4000/64/32/32' \
169+
--benchmark_min_time=0.05s \
170+
--benchmark_repetitions=5 \
171+
--benchmark_report_aggregates_only=true \
172+
--benchmark_out=artifacts/perf/base/bench_diffgeo_base.json \
173+
--benchmark_out_format=json > artifacts/perf/base/bench_diffgeo_base.txt
174+
else
175+
echo "bench_diffgeo target not available on baseline ${{ steps.baseline.outputs.base_sha }}" > artifacts/perf/base/bench_diffgeo_base.txt
176+
fi
177+
158178
- name: Compare benchmark deltas
159179
shell: bash
160180
run: |
@@ -216,6 +236,24 @@ jobs:
216236
> artifacts/perf/reports/bench_pipelines_smoke.json
217237
fi
218238
239+
if [[ -s artifacts/perf/base/bench_diffgeo_base.json ]]; then
240+
python3 scripts/perf/compare_against_main.py \
241+
--baseline artifacts/perf/base/bench_diffgeo_base.json \
242+
--current artifacts/perf/head/bench_diffgeo_head.json \
243+
--baseline-commit "${{ steps.baseline.outputs.base_sha }}" \
244+
--label "PR smoke: bench_diffgeo (baseline ${{ steps.baseline.outputs.base_sha }})" \
245+
--output-markdown artifacts/perf/reports/bench_diffgeo_smoke.md \
246+
--output-json artifacts/perf/reports/bench_diffgeo_smoke.json
247+
else
248+
python3 scripts/perf/compare_against_main.py \
249+
--baseline artifacts/perf/base/bench_diffgeo_base.txt \
250+
--current artifacts/perf/head/bench_diffgeo_head.json \
251+
--baseline-commit "${{ steps.baseline.outputs.base_sha }}" \
252+
--label "PR smoke: bench_diffgeo (baseline ${{ steps.baseline.outputs.base_sha }})" \
253+
--output-markdown artifacts/perf/reports/bench_diffgeo_smoke.md \
254+
--output-json artifacts/perf/reports/bench_diffgeo_smoke.json
255+
fi
256+
219257
{
220258
echo "# Perf Smoke Report"
221259
echo
@@ -229,6 +267,8 @@ jobs:
229267
cat artifacts/perf/reports/bench_dod_smoke.md
230268
echo
231269
cat artifacts/perf/reports/bench_pipelines_smoke.md
270+
echo
271+
cat artifacts/perf/reports/bench_diffgeo_smoke.md
232272
} > artifacts/perf/reports/smoke-summary.md
233273
234274
- name: Publish job summary

include/igneous/ops/dec/curvature.hpp

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,130 @@ void compute_curvature_measures(const data::Space<StructureT>& space, std::vecto
4444

4545
workspace.face_normals.resize(num_faces);
4646

47+
if constexpr (std::is_same_v<StructureT, data::DiscreteExteriorCalculus>) {
48+
const auto& x = space.x;
49+
const auto& y = space.y;
50+
const auto& z = space.z;
51+
const auto& face_v0 = structure.face_v0;
52+
const auto& face_v1 = structure.face_v1;
53+
const auto& face_v2 = structure.face_v2;
54+
const auto& vertex_face_offsets = structure.vertex_face_offsets;
55+
const auto& vertex_face_data = structure.vertex_face_data;
56+
57+
core::parallel_for_index(
58+
0, static_cast<int>(num_faces),
59+
[&](int face_idx) {
60+
const size_t f = static_cast<size_t>(face_idx);
61+
const uint32_t i0 = face_v0[f];
62+
const uint32_t i1 = face_v1[f];
63+
const uint32_t i2 = face_v2[f];
64+
65+
const float e10x = x[i1] - x[i0];
66+
const float e10y = y[i1] - y[i0];
67+
const float e10z = z[i1] - z[i0];
68+
const float e20x = x[i2] - x[i0];
69+
const float e20y = y[i2] - y[i0];
70+
const float e20z = z[i2] - z[i0];
71+
72+
workspace.face_normals[f] = {
73+
e10x * e20y - e10y * e20x,
74+
e10y * e20z - e10z * e20y,
75+
e10z * e20x - e10x * e20z,
76+
};
77+
},
78+
256);
79+
80+
core::parallel_for_index(
81+
0, static_cast<int>(num_verts),
82+
[&](int vertex_idx) {
83+
const size_t i = static_cast<size_t>(vertex_idx);
84+
const uint32_t begin = vertex_face_offsets[i];
85+
const uint32_t end = vertex_face_offsets[i + 1];
86+
if (begin == end) {
87+
return;
88+
}
89+
90+
float angle_sum = 0.0f;
91+
float area_sum = 0.0f;
92+
93+
float n_xy = 0.0f;
94+
float n_yz = 0.0f;
95+
float n_zx = 0.0f;
96+
97+
float sum_x = 0.0f;
98+
float sum_y = 0.0f;
99+
float sum_z = 0.0f;
100+
101+
const float px = x[i];
102+
const float py = y[i];
103+
const float pz = z[i];
104+
105+
for (uint32_t idx = begin; idx < end; ++idx) {
106+
const uint32_t f_idx = vertex_face_data[idx];
107+
const core::Bivec3 fn = workspace.face_normals[f_idx];
108+
n_xy += fn.xy;
109+
n_yz += fn.yz;
110+
n_zx += fn.zx;
111+
112+
const uint32_t i0 = face_v0[f_idx];
113+
const uint32_t i1 = face_v1[f_idx];
114+
const uint32_t i2 = face_v2[f_idx];
115+
116+
uint32_t a = i0;
117+
uint32_t b = i1;
118+
if (i0 == i) {
119+
a = i1;
120+
b = i2;
121+
} else if (i1 == i) {
122+
a = i2;
123+
b = i0;
124+
}
125+
126+
const float ux = x[a] - px;
127+
const float uy = y[a] - py;
128+
const float uz = z[a] - pz;
129+
const float vx = x[b] - px;
130+
const float vy = y[b] - py;
131+
const float vz = z[b] - pz;
132+
133+
const float dot = ux * vx + uy * vy + uz * vz;
134+
const float wedge_xy = ux * vy - uy * vx;
135+
const float wedge_yz = uy * vz - uz * vy;
136+
const float wedge_zx = uz * vx - ux * vz;
137+
const float wedge_mag =
138+
std::sqrt(wedge_xy * wedge_xy + wedge_yz * wedge_yz + wedge_zx * wedge_zx);
139+
140+
angle_sum += std::atan2(wedge_mag, dot);
141+
area_sum += 0.5f * wedge_mag;
142+
143+
sum_x += x[a] + x[b];
144+
sum_y += y[a] + y[b];
145+
sum_z += z[a] + z[b];
146+
}
147+
148+
if (area_sum > 1e-12f) {
149+
K[i] = static_cast<float>((2.0 * std::numbers::pi_v<double> - angle_sum) /
150+
(static_cast<double>(area_sum) / 3.0));
151+
}
152+
153+
const float n_mag_sq = n_xy * n_xy + n_yz * n_yz + n_zx * n_zx;
154+
const float n_inv = (n_mag_sq > 1e-12f) ? 1.0f / std::sqrt(n_mag_sq) : 0.0f;
155+
156+
const float normal_x = n_yz * n_inv;
157+
const float normal_y = n_zx * n_inv;
158+
const float normal_z = n_xy * n_inv;
159+
160+
const float inv_c = 0.5f / static_cast<float>(end - begin);
161+
const float laplacian_x = sum_x * inv_c - px;
162+
const float laplacian_y = sum_y * inv_c - py;
163+
const float laplacian_z = sum_z * inv_c - pz;
164+
165+
H[i] = laplacian_x * normal_x + laplacian_y * normal_y + laplacian_z * normal_z;
166+
},
167+
128);
168+
return;
169+
}
170+
47171
const auto get_face_vertex = [&](size_t face_idx, int corner) -> uint32_t {
48172
if constexpr (std::is_same_v<StructureT, data::DiscreteExteriorCalculus>) {
49173
if (corner == 0)

0 commit comments

Comments
 (0)