Skip to content

Speed up to_raster() by pruning candidates by their own radii; create Grid.compute_face_radii() - #1825

Merged
cmdupuis3 merged 11 commits into
mainfrom
sevans/face_radii-and-to_raster-speedup
Oct 28, 2026
Merged

cmdupuis3 merged 11 commits into
mainfrom
sevans/face_radii-and-to_raster-speedup

Conversation

@Sevans711

@Sevans711 Sevans711 commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #1807, closes #1808

Overview

For #1808, creates Grid.compute_face_radii(), along with test_face_radii() to test it (and also to test Grid.max_face_radius, which was previously not mentioned explicitly anywhere in the test suite).

For #1807, creates _cull_candidates_by_radius() and uses it inside _point_in_face_query() to efficiently drop any candidates whose face radius is small enough that there is no possible way for the target point to be contained inside the face. Also added some thresholds to avoid running this cull in cases where there are "not many" candidates in total or "not many" candidates per point (before adding these thresholds, various ASV benchmarks showed slowdowns).

I believe there are no surprises / expansions of scope in here; all changes go directly towards addressing the original issues.

Expected Usage

import uxarray as ux

grid_path = "/path/to/grid.nc"
data_path = "/path/to/data.nc"
uxds = ux.open_dataset(grid_path, data_path)
grid = uxds.uxgrid

radii = grid.compute_face_radii()
# radii is now a UxDataArray with dims ["n_face"],
# and values equal to the radius of each face.

PR Checklist

General

  • An issue is created and linked
  • Added appropriate labels (if your uxarray repo permissions allow it)
  • Filled out Overview and Expected Usage (if applicable) sections

Testing & Benchmarking

  • There is adequate test coverage of changes from this PR (add new tests if needed)
  • If this PR could affect performance, ran ASV benchmarks and confirmed they show expected behavior (add a new benchmark if necessary)

Documentation and Examples

  • Docstrings updated with any function changes, and included in all new functions
  • User (public) functions added to docs/api.rst; internal (private) function names start with an underscore (_)
  • [N/A] If touched any notebook files, cleared the output of all cells before committing
  • [N/A] If added new notebook files, put into appropriate directories and referenced in appropriate files

AI Disclosure

AI Usage: Claude and GitHub Copilot's inline code suggestions

  • I have tested and take responsibility for all AI-generated content in my PR.

@Sevans711 Sevans711 added new feature New user-facing functionality scalability Related to scalability & performance efforts run-benchmark Run ASV benchmark workflow visualization Plotting or other visualizations labels Oct 14, 2026
@github-actions

github-actions Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

ASV Benchmarking

Benchmark Comparison Results

Benchmarks that have improved:

Change Before [8d36335] After [947de25] Ratio Benchmark (Parameter)
- 1.12±0s 735±4ms 0.66 to_raster.ToRaster.time_to_raster((10000.0, 10.0))
- 2.79±0.03s 1.53±0.01s 0.55 to_raster.ToRaster.time_to_raster((10000.0, 100.0))
- 3.17±0.03s 1.78±0.02s 0.56 to_raster.ToRaster.time_to_raster((100000.0, 100.0))

Benchmarks that have stayed the same:

Change Before [8d36335] After [947de25] Ratio Benchmark (Parameter)
697±10μs 700±20μs 1.00 connectivity.Connectivity.time_edge_face('120km')
244±10μs 245±7μs 1.00 connectivity.Connectivity.time_edge_face('480km')
3.59±0.08ms 3.56±0.06ms 0.99 connectivity.Connectivity.time_edge_node('120km')
578±10μs 599±40μs 1.04 connectivity.Connectivity.time_edge_node('480km')
34.9±3μs 38.1±5μs 1.09 connectivity.Connectivity.time_face_edge('120km')
30.5±2μs 32.5±7μs 1.07 connectivity.Connectivity.time_face_edge('480km')
413±10μs 425±20μs 1.03 connectivity.Connectivity.time_face_face('120km')
233±5μs 242±20μs 1.04 connectivity.Connectivity.time_face_face('480km')
30.8±4μs 31.5±4μs 1.02 connectivity.Connectivity.time_face_node('120km')
30.5±9μs 33.1±7μs 1.09 connectivity.Connectivity.time_face_node('480km')
244±20μs 262±20μs 1.07 connectivity.Connectivity.time_n_nodes_per_face('120km')
194±20μs 216±10μs ~1.11 connectivity.Connectivity.time_n_nodes_per_face('480km')
643±30μs 693±30μs 1.08 connectivity.Connectivity.time_node_edge('120km')
225±8μs 247±10μs 1.10 connectivity.Connectivity.time_node_edge('480km')
44.0±3ms 45.9±3ms 1.04 connectivity.Connectivity.time_node_face('120km')
2.55±0.02ms 2.76±0.1ms 1.08 connectivity.Connectivity.time_node_face('480km')
1.42M 1.42M 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_edge_face('120km')
105k 105k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_edge_face('480km')
6.48M 6.48M 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_edge_node('120km')
419k 419k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_edge_node('480km')
2.05k 2.05k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_face_edge('120km')
2.05k 2.05k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_face_edge('480km')
1.6M 1.6M 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_face_face('120km')
101k 101k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_face_face('480km')
2.18k 2.18k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_face_node('120km')
2.18k 2.18k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_face_node('480km')
240k 240k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_n_nodes_per_face('120km')
26k 26k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_n_nodes_per_face('480km')
1.9M 1.9M 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_node_edge('120km')
127k 127k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_node_edge('480km')
11.9M 11.9M 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_node_face('120km')
747k 747k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_node_face('480km')
5.67±0.04ms 5.67±0.08ms 1.00 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
1.75±0.04ms 1.79±0.04ms 1.02 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
7.23±0.03ms 7.23±8ms 1.00 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
956±30μs 963±10μs 1.01 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
57.3k 57.3k 1.00 face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
12.3k 12.3k 1.00 face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
123k 123k 1.00 face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
128 128 1.00 face_bounds.FaceBounds.track_nbytes_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
1.27M 1.27M 1.00 face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
50.1k 50.1k 1.00 face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
1.48M 1.48M 1.00 face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
712 712 1.00 face_bounds.FaceBounds.track_nbytes_grid_with_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
1.89M 1.89M 1.00 face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
1.88M 1.88M 1.00 face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
2.04M 2.04M 1.00 face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
35.3k 35.3k 1.00 face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
1.18±0.03μs 1.19±0.02μs 1.01 geometry_kernels.AccucrossKernels.time_accucross
2.65±0.03μs 2.68±0.02μs 1.01 geometry_kernels.AccucrossKernels.time_accucross_pair
506±20ns 485±30ns 0.96 geometry_kernels.EFTPrimitives.time_acc_sqrt_re
516±40ns 471±20ns 0.91 geometry_kernels.EFTPrimitives.time_diff_of_products
421±30ns 400±20ns 0.95 geometry_kernels.EFTPrimitives.time_two_prod
451±10ns 441±20ns 0.98 geometry_kernels.EFTPrimitives.time_two_sum
486±5ns 496±20ns 1.02 geometry_kernels.GCAConstLatIntersection.time_accux_constlat_kernel
521±90ns 526±10ns 1.01 geometry_kernels.GCAConstLatIntersection.time_gca_const_lat_intersection
566±10ns 561±9ns 0.99 geometry_kernels.GCAConstLatIntersection.time_try_gca_const_lat_intersection
821±20ns 832±10ns 1.01 geometry_kernels.GCAGCAIntersection.time_accux_gca_kernel
892±20ns 932±50ns 1.04 geometry_kernels.GCAGCAIntersection.time_gca_gca_intersection
1.05±0.01μs 1.11±0.01μs 1.06 geometry_kernels.GCAGCAIntersection.time_try_gca_gca_intersection
28.1±0.2μs 28.5±0.3μs 1.01 geometry_kernels.OrientPredicates.time_on_minor_arc
27.7±0.2μs 28.3±0.3μs 1.02 geometry_kernels.OrientPredicates.time_orient3d_on_sphere
3.06±0ms 3.09±0.02ms 1.01 geometry_samebody.SameBodyConstLat.time_accux_dispatch
1.16±0ms 1.16±0ms 1.00 geometry_samebody.SameBodyConstLat.time_accux_kernel
2.29±0ms 2.31±0.01ms 1.01 geometry_samebody.SameBodyConstLat.time_fp64_dispatch
148±4μs 148±4μs 1.00 geometry_samebody.SameBodyConstLat.time_fp64_kernel
23.3±0.1ms 23.2±0.01ms 0.99 geometry_samebody_gcagca.SameBodyGcaGca.time_accux_dispatch
5.53±0ms 5.47±0.06ms 0.99 geometry_samebody_gcagca.SameBodyGcaGca.time_accux_kernel
17.6±0.04ms 17.8±0.06ms 1.01 geometry_samebody_gcagca.SameBodyGcaGca.time_fp64_dispatch
699±1μs 697±0.7μs 1.00 geometry_samebody_gcagca.SameBodyGcaGca.time_fp64_kernel
901±10ms 889±7ms 0.99 import.Imports.timeraw_import_uxarray
1 1 1.00 lazy_grid_construction.LazyGridConstruction.track_computes_isel
2 2 1.00 lazy_grid_construction.LazyGridConstruction.track_computes_open_grid_chunked
97.9±2ms 95.6±0.6ms 0.98 lazy_grid_construction.OpenGridChunked.time_open_grid('120km')
134±2ms 133±2ms 0.99 lazy_grid_construction.OpenGridChunked.time_open_grid('480km')
1.99M 1.99M 1.00 lazy_grid_construction.OpenGridChunked.track_peakmem_open_grid('120km')
2.32M 2.38M 1.03 lazy_grid_construction.OpenGridChunked.track_peakmem_open_grid('480km')
2.42±0.05ms 2.32±0.02ms 0.96 mpas_ocean.CheckNorm.time_check_norm('120km')
1.91±0.02ms 1.86±0.01ms 0.97 mpas_ocean.CheckNorm.time_check_norm('480km')
1.11±0ms 1.14±0.01ms 1.02 mpas_ocean.ConnectivityConstruction.time_face_face_connectivity('120km')
527±2μs 529±7μs 1.01 mpas_ocean.ConnectivityConstruction.time_face_face_connectivity('480km')
618±10μs 627±10μs 1.01 mpas_ocean.ConnectivityConstruction.time_n_nodes_per_face('120km')
561±10μs 578±4μs 1.03 mpas_ocean.ConnectivityConstruction.time_n_nodes_per_face('480km')
5.03±0.02ms 5.07±0.01ms 1.01 mpas_ocean.ConstructFaceLatLon.time_cartesian_averaging('120km')
3.54±0.03ms 3.58±0.01ms 1.01 mpas_ocean.ConstructFaceLatLon.time_cartesian_averaging('480km')
95.6±0.1ms 96.7±1ms 1.01 mpas_ocean.ConstructFaceLatLon.time_welzl('120km')
9.04±0.03ms 9.36±0.3ms 1.04 mpas_ocean.ConstructFaceLatLon.time_welzl('480km')
18.7±0.05ms 18.7±0.1ms 1.00 mpas_ocean.ConstructTreeStructures.time_ball_tree('120km')
944±9μs 938±20μs 0.99 mpas_ocean.ConstructTreeStructures.time_ball_tree('480km')
9.90±0.07ms 9.85±0.05ms 1.00 mpas_ocean.ConstructTreeStructures.time_kd_tree('120km')
587±6μs 577±20μs 0.98 mpas_ocean.ConstructTreeStructures.time_kd_tree('480km')
424±6ms 425±7ms 1.00 mpas_ocean.CrossSections.time_const_lat('120km', 1)
214±1ms 212±3ms 0.99 mpas_ocean.CrossSections.time_const_lat('120km', 2)
114±1ms 112±0.8ms 0.98 mpas_ocean.CrossSections.time_const_lat('120km', 4)
374±2ms 364±0.6ms 0.97 mpas_ocean.CrossSections.time_const_lat('480km', 1)
190±4ms 186±3ms 0.98 mpas_ocean.CrossSections.time_const_lat('480km', 2)
95.6±0.5ms 96.1±0.3ms 1.01 mpas_ocean.CrossSections.time_const_lat('480km', 4)
25.0±0.06ms 24.9±0.1ms 1.00 mpas_ocean.DualMesh.time_dual_mesh_construction('120km')
2.92±0.02ms 2.98±0.06ms 1.02 mpas_ocean.DualMesh.time_dual_mesh_construction('480km')
7.52±0.5ms 7.78±0.6ms 1.03 mpas_ocean.FaceAreas.time_face_areas('120km')
2.06±0.08ms 2.04±0.2ms 0.99 mpas_ocean.FaceAreas.time_face_areas('480km')
229k 229k 1.00 mpas_ocean.FaceAreas.track_nbytes_face_areas('120km')
14.3k 14.3k 1.00 mpas_ocean.FaceAreas.track_nbytes_face_areas('480km')
2.12M 2.12M 1.00 mpas_ocean.FaceAreas.track_peakmem_face_areas('120km')
735k 735k 1.00 mpas_ocean.FaceAreas.track_peakmem_face_areas('480km')
42.4±0.7ms 42.5±0.8ms 1.00 mpas_ocean.GeoDataFrame.time_to_geodataframe('120km', 'exclude')
108±0.2ms 110±1ms 1.01 mpas_ocean.GeoDataFrame.time_to_geodataframe('120km', 'split')
3.79±0.2ms 3.91±0.2ms 1.03 mpas_ocean.GeoDataFrame.time_to_geodataframe('480km', 'exclude')
19.5±0.3ms 20.6±0.2ms 1.06 mpas_ocean.GeoDataFrame.time_to_geodataframe('480km', 'split')
14.1±0.4ms 13.7±0.1ms 0.97 mpas_ocean.Gradient.time_gradient('120km')
2.41±0.01ms 2.36±0.01ms 0.98 mpas_ocean.Gradient.time_gradient('480km')
457k 457k 1.00 mpas_ocean.Gradient.track_nbytes_gradient('120km')
28.7k 28.7k 1.00 mpas_ocean.Gradient.track_nbytes_gradient('480km')
3.44M 3.44M 1.00 mpas_ocean.Gradient.track_peakmem_gradient('120km')
226k 226k 1.00 mpas_ocean.Gradient.track_peakmem_gradient('480km')
155±7μs 150±2μs 0.96 mpas_ocean.HoleEdgeIndices.time_construct_hole_edge_indices('120km')
63.9±0.3μs 64.8±0.6μs 1.01 mpas_ocean.HoleEdgeIndices.time_construct_hole_edge_indices('480km')
77.2±0.5μs 78.4±0.7μs 1.02 mpas_ocean.Integrate.time_integrate('120km')
69.4±0.5μs 71.7±0.4μs 1.03 mpas_ocean.Integrate.time_integrate('480km')
18.4M 18.4M 1.00 mpas_ocean.Integrate.track_nbytes_integrate('120km')
1.2M 1.2M 1.00 mpas_ocean.Integrate.track_nbytes_integrate('480km')
137±1ms 137±1ms 1.00 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'exclude')
137±2ms 138±2ms 1.00 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'include')
137±1ms 135±0.9ms 0.99 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'split')
9.73±0.03ms 9.79±0.2ms 1.01 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'exclude')
9.78±0.08ms 9.72±0.07ms 0.99 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'include')
9.76±0.03ms 9.64±0.06ms 0.99 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'split')
209±0.5ms 210±0.8ms 1.00 mpas_ocean.NeighborhoodBuild.time_build('120km', 1.0)
435±0.9ms 433±1ms 1.00 mpas_ocean.NeighborhoodBuild.time_build('120km', 5.0)
11.3±0.1ms 11.3±0.07ms 1.00 mpas_ocean.NeighborhoodBuild.time_build('480km', 1.0)
14.0±0.5ms 13.9±0.07ms 0.99 mpas_ocean.NeighborhoodBuild.time_build('480km', 5.0)
206±0.5ms 207±0.6ms 1.00 mpas_ocean.NeighborhoodBuild.time_query_radius('120km', 1.0)
428±0.2ms 429±2ms 1.00 mpas_ocean.NeighborhoodBuild.time_query_radius('120km', 5.0)
11.0±0.1ms 11.0±0.05ms 1.00 mpas_ocean.NeighborhoodBuild.time_query_radius('480km', 1.0)
13.5±0.04ms 13.6±0.05ms 1.01 mpas_ocean.NeighborhoodBuild.time_query_radius('480km', 5.0)
612.76 612.76 1.00 mpas_ocean.NeighborhoodBuild.track_mean_neighbors('120km', 15.0)
74.17 74.17 1.00 mpas_ocean.NeighborhoodBuild.track_mean_neighbors('120km', 5.0)
37.29 37.29 1.00 mpas_ocean.NeighborhoodBuild.track_mean_neighbors('480km', 15.0)
6.57 6.57 1.00 mpas_ocean.NeighborhoodBuild.track_mean_neighbors('480km', 5.0)
141M 141M 1.00 mpas_ocean.NeighborhoodBuild.track_nbytes_neighbors('120km', 15.0)
17.4M 17.4M 1.00 mpas_ocean.NeighborhoodBuild.track_nbytes_neighbors('120km', 5.0)
563k 563k 1.00 mpas_ocean.NeighborhoodBuild.track_nbytes_neighbors('480km', 15.0)
123k 123k 1.00 mpas_ocean.NeighborhoodBuild.track_nbytes_neighbors('480km', 5.0)
145M 145M 1.00 mpas_ocean.NeighborhoodBuild.track_peakmem_build('120km', 15.0)
21.5M 21.5M 1.00 mpas_ocean.NeighborhoodBuild.track_peakmem_build('120km', 5.0)
824k 824k 1.00 mpas_ocean.NeighborhoodBuild.track_peakmem_build('480km', 15.0)
384k 384k 1.00 mpas_ocean.NeighborhoodBuild.track_peakmem_build('480km', 5.0)
39.2±0.4ms 38.8±1ms 0.99 mpas_ocean.NeighborhoodDask.time_mean('120km', 'grid_chunks')
18.1±0.05ms 18.0±0.03ms 0.99 mpas_ocean.NeighborhoodDask.time_mean('120km', 'numpy')
36.6±0.9ms 35.6±1ms 0.97 mpas_ocean.NeighborhoodDask.time_mean('120km', 'time_chunks')
10.3±0.1ms 10.2±0.1ms 0.99 mpas_ocean.NeighborhoodDask.time_mean('480km', 'grid_chunks')
619±5μs 627±4μs 1.01 mpas_ocean.NeighborhoodDask.time_mean('480km', 'numpy')
7.12±0.08ms 7.12±0.08ms 1.00 mpas_ocean.NeighborhoodDask.time_mean('480km', 'time_chunks')
5.9M 5.9M 1.00 mpas_ocean.NeighborhoodDask.track_peakmem_mean('120km', 'grid_chunks')
2.75M 2.75M 1.00 mpas_ocean.NeighborhoodDask.track_peakmem_mean('120km', 'numpy')
5.67M 5.68M 1.00 mpas_ocean.NeighborhoodDask.track_peakmem_mean('120km', 'time_chunks')
177k 177k 1.00 mpas_ocean.NeighborhoodDask.track_peakmem_mean('480km', 'numpy')
521k 527k 1.01 mpas_ocean.NeighborhoodDask.track_peakmem_mean('480km', 'time_chunks')
3.12±0.01s 3.14±0.03s 1.01 mpas_ocean.NeighborhoodReduce.time_dataset_reduce('120km', 'mean')
3.25±0.04s 3.20±0.09s 0.99 mpas_ocean.NeighborhoodReduce.time_dataset_reduce('120km', 'median')
80.8±2ms 84.4±3ms 1.04 mpas_ocean.NeighborhoodReduce.time_dataset_reduce('480km', 'mean')
83.2±0.8ms 82.3±0.8ms 0.99 mpas_ocean.NeighborhoodReduce.time_dataset_reduce('480km', 'median')
360±3ms 354±4ms 0.98 mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('120km', 'mean')
387±2ms 384±9ms 0.99 mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('120km', 'median')
11.5±0.1ms 11.5±0.05ms 1.00 mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('480km', 'mean')
11.7±2ms 11.7±0.3ms 1.00 mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('480km', 'median')
2.38±0.05ms 2.43±0.04ms 1.02 mpas_ocean.NeighborhoodReduce.time_reduce('120km', 'mean')
27.6±0.2ms 26.0±0.3ms 0.94 mpas_ocean.NeighborhoodReduce.time_reduce('120km', 'median')
110±0.9μs 109±0.2μs 0.99 mpas_ocean.NeighborhoodReduce.time_reduce('480km', 'mean')
335±6μs 328±4μs 0.98 mpas_ocean.NeighborhoodReduce.time_reduce('480km', 'median')
234k 234k 1.00 mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('120km', 'mean')
235k 235k 1.00 mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('120km', 'median')
19.5k 19.5k 1.00 mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('480km', 'mean')
19.6k 19.6k 1.00 mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('480km', 'median')
354±7μs 363±8μs 1.03 mpas_ocean.PointInPolygon.time_face_search_lonlat('120km')
331±30μs 364±5μs ~1.10 mpas_ocean.PointInPolygon.time_face_search_lonlat('480km')
324±20μs 337±4μs 1.04 mpas_ocean.PointInPolygon.time_face_search_xyz('120km')
327±20μs 325±20μs 1.00 mpas_ocean.PointInPolygon.time_face_search_xyz('480km')
78.5±0.6ms 78.1±1ms 0.99 mpas_ocean.RemapDownsample.time_bilinear_remapping
12.8±0.1ms 12.8±0.07ms 1.00 mpas_ocean.RemapDownsample.time_inverse_distance_weighted_remapping
11.8±0.04ms 11.8±0.06ms 0.99 mpas_ocean.RemapDownsample.time_nearest_neighbor_remapping
1.07±0.01s 1.09±0s 1.02 mpas_ocean.RemapUpsample.time_bilinear_remapping
25.7±0.06ms 25.4±0.06ms 0.99 mpas_ocean.RemapUpsample.time_inverse_distance_weighted_remapping
11.0±0.04ms 11.0±0.1ms 1.00 mpas_ocean.RemapUpsample.time_nearest_neighbor_remapping
5.89±0.08ms 5.78±0.09ms 0.98 mpas_ocean.ZonalAverage.time_zonal_average('120km')
3.34±0.02ms 3.35±0.1ms 1.01 mpas_ocean.ZonalAverage.time_zonal_average('480km')
1.0361537814162451 1.037964659890839 1.00 nogil_scaling.GILScaling.track_gil_scaling
315±2ms 316±2ms 1.00 plots.PlotHealpix.time_default_plot(6)
2.81±0.01s 2.81±0.02s 1.00 plots.PlotHealpix.time_default_plot(8)
28M 27.9M 1.00 plots.PlotHealpix.track_peakmem_default_plot(6)
443M 443M 1.00 plots.PlotHealpix.track_peakmem_default_plot(8)
5.48±0.03ms 5.50±0.02ms 1.00 quad_hexagon.QuadHexagon.time_open_dataset
4.72±0.09ms 4.65±0.08ms 0.99 quad_hexagon.QuadHexagon.time_open_grid
408 408 1.00 quad_hexagon.QuadHexagon.track_nbytes_open_dataset
392 392 1.00 quad_hexagon.QuadHexagon.track_nbytes_open_grid
70.1k 70.1k 1.00 quad_hexagon.QuadHexagon.track_peakmem_open_dataset
69.9k 69.9k 1.00 quad_hexagon.QuadHexagon.track_peakmem_open_grid
270M 270M 1.00 to_raster.ToRaster.track_peakmem((10000.0, 10.0))
680M 680M 1.00 to_raster.ToRaster.track_peakmem((10000.0, 100.0))
765M 765M 1.00 to_raster.ToRaster.track_peakmem((100000.0, 100.0))

Benchmarks that have got worse:

Change Before [8d36335] After [947de25] Ratio Benchmark (Parameter)
+ 301M 386M 1.28 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
+ 301M 386M 1.28 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
+ 303M 386M 1.27 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
+ 303M 386M 1.28 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
+ 277M 385M 1.39 import.Imports.track_peakmem_import_uxarray
+ 321M 386M 1.2 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('120km', 1)
+ 321M 386M 1.2 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('120km', 2)
+ 321M 386M 1.2 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('120km', 4)
+ 304M 386M 1.27 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('480km', 1)
+ 304M 386M 1.27 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('480km', 2)
+ 304M 386M 1.27 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('480km', 4)
+ 317M 386M 1.22 mpas_ocean.GradientColdStartRss.track_peakmem_gradient('120km')
+ 297M 386M 1.3 mpas_ocean.GradientColdStartRss.track_peakmem_gradient('480km')
+ 668k 755k 1.13 mpas_ocean.NeighborhoodDask.track_peakmem_mean('480km', 'grid_chunks')
+ 322M 385M 1.2 mpas_ocean.ZonalAveragePeakMem.track_peakmem_zonal_average('120km')
+ 305M 385M 1.27 mpas_ocean.ZonalAveragePeakMem.track_peakmem_zonal_average('480km')

to avoid regressions to performance in "only a few candidates per point" cases and in "only a few candidates total" cases.
@Sevans711
Sevans711 marked this pull request as ready for review October 14, 2026 15:16

@dylannelson dylannelson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks good on my end, speedup is seen and has been demonstrated multiple ways locally. One new warning that popped up on my end, but I'm not as certain about the cause, but commented about where it seems to be. Maybe of others can give some feedback. It seems like it's the same error seen here in #1358, NumbaPerformanceWarning, which was also solved recently in the other speedup PR.

Comment thread uxarray/grid/geometry.py Outdated
it was adding unnecessary complexity and a NumbaPerformanceWarning, there was no need for it to be jitted since it was just taking a max(), now that _compute_face_radii() handles the looping through faces.
@Sevans711
Sevans711 requested a review from dylannelson October 15, 2026 18:45
Comment thread uxarray/grid/point_in_face.py Outdated
Comment thread docs/api.rst
Comment thread uxarray/grid/point_in_face.py Outdated
@cmdupuis3
cmdupuis3 self-requested a review October 28, 2026 15:02
@dylannelson

Copy link
Copy Markdown
Member

The numba comment has been resolved and I see no other concerns. Speed up is present and all looks good. Thanks!

@cmdupuis3
cmdupuis3 merged commit d4ebb8a into main Oct 28, 2026
18 of 19 checks passed
@Sevans711
Sevans711 deleted the sevans/face_radii-and-to_raster-speedup branch October 28, 2026 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new feature New user-facing functionality run-benchmark Run ASV benchmark workflow scalability Related to scalability & performance efforts visualization Plotting or other visualizations

Projects

None yet

3 participants