Skip to content

Optimize _get_faces_constLat_intersection_info - #1799

Draft
cmdupuis3 wants to merge 7 commits into
UXARRAY:mainfrom
cmdupuis3:cmd/optimize_integrate
Draft

cmdupuis3 wants to merge 7 commits into
UXARRAY:mainfrom
cmdupuis3:cmd/optimize_integrate

Conversation

@cmdupuis3

@cmdupuis3 cmdupuis3 commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #1570

Maybe related to #790

Overview

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 (_)

AI Disclosure

AI Usage: Claude Opus 5

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

@cmdupuis3 cmdupuis3 self-assigned this Sep 30, 2026
@cmdupuis3 cmdupuis3 added scalability Related to scalability & performance efforts run-benchmark Run ASV benchmark workflow labels Sep 30, 2026
cmdupuis3 and others added 2 commits September 30, 2026 13:30
Adapt the Numba intersection kernel to two changes on main:

- UXARRAY#1727 changed gca_const_lat_intersection to return a tuple of tuples
  instead of a (2, 3) array, so the kernel now reads points as
  intersections[r][i] rather than intersections[r, i].
- UXARRAY#1705 made the no-intersection and concave-face errors format the face
  array into their messages, which Numba cannot do, so both raises move
  from the kernel into the Python wrapper. The kernel now also returns the
  number of non-dummy edges that the concave check needs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

ASV Benchmarking

Benchmark Comparison Results

Benchmarks that have improved:

Change Before [03cb40d] After [32a4fb1] Ratio Benchmark (Parameter)
- 2.28±0s 15.3±2ms 0.01 mpas_ocean.ZonalAverage.time_zonal_average_robust('120km')
- 567±1ms 6.23±0.03ms 0.01 mpas_ocean.ZonalAverage.time_zonal_average_robust('480km')

Benchmarks that have stayed the same:

Change Before [03cb40d] After [32a4fb1] Ratio Benchmark (Parameter)
979±20μs 978±20μs 1.00 connectivity.Connectivity.time_edge_face('120km')
490±20μs 485±10μs 0.99 connectivity.Connectivity.time_edge_face('480km')
3.95±0.04ms 4.01±0.08ms 1.01 connectivity.Connectivity.time_edge_node('120km')
1.31±0.05ms 1.28±0.03ms 0.98 connectivity.Connectivity.time_edge_node('480km')
75.0±6μs 72.4±4μs 0.97 connectivity.Connectivity.time_face_edge('120km')
69.8±6μs 71.3±3μs 1.02 connectivity.Connectivity.time_face_edge('480km')
1.02±0.02ms 981±20μs 0.96 connectivity.Connectivity.time_face_face('120km')
409±20μs 421±20μs 1.03 connectivity.Connectivity.time_face_face('480km')
64.8±20μs 68.4±9μs 1.06 connectivity.Connectivity.time_face_node('120km')
63.5±10μs 61.9±3μs 0.97 connectivity.Connectivity.time_face_node('480km')
511±50μs 506±40μs 0.99 connectivity.Connectivity.time_n_nodes_per_face('120km')
430±20μs 431±20μs 1.00 connectivity.Connectivity.time_n_nodes_per_face('480km')
1.40±0.01ms 1.39±0.02ms 0.99 connectivity.Connectivity.time_node_edge('120km')
497±10μs 494±10μs 0.99 connectivity.Connectivity.time_node_edge('480km')
77.9±3ms 77.0±0.6ms 0.99 connectivity.Connectivity.time_node_face('120km')
4.98±0.04ms 5.04±0.06ms 1.01 connectivity.Connectivity.time_node_face('480km')
1.42M 1.42M 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_edge_face('120km')
106k 106k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_edge_face('480km')
6.48M 6.48M 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_edge_node('120km')
420k 420k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_edge_node('480km')
2.42k 2.42k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_face_edge('120km')
2.42k 2.42k 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.54k 2.54k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_face_node('120km')
2.54k 2.54k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_face_node('480km')
240k 240k 1.00 connectivity.ConnectivityTracemalloc.track_peakmem_n_nodes_per_face('120km')
26.3k 26.3k 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')
8.38±0.06ms 8.35±0.2ms 1.00 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
2.70±0.03ms 2.78±0.07ms 1.03 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
10.3±0.2ms 10.2±9ms 1.00 face_bounds.FaceBounds.time_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
1.54±0.02ms 1.62±0.04ms 1.05 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.85M 1.85M 1.00 face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
1.85M 1.85M 1.00 face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
2.01M 2.01M 1.00 face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
35.6k 35.6k 1.00 face_bounds.FaceBounds.track_peakmem_face_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
1.20±0.02μs 1.17±0.03μs 0.97 geometry_kernels.AccucrossKernels.time_accucross
2.61±0.02μs 2.63±0.03μs 1.00 geometry_kernels.AccucrossKernels.time_accucross_pair
451±20ns 461±10ns 1.02 geometry_kernels.EFTPrimitives.time_acc_sqrt_re
426±20ns 436±20ns 1.02 geometry_kernels.EFTPrimitives.time_diff_of_products
376±9ns 396±5ns 1.05 geometry_kernels.EFTPrimitives.time_two_prod
390±9ns 391±10ns 1.00 geometry_kernels.EFTPrimitives.time_two_sum
681±20ns 696±20ns 1.02 geometry_kernels.GCAConstLatIntersection.time_accux_constlat_kernel
727±20ns 726±20ns 1.00 geometry_kernels.GCAConstLatIntersection.time_gca_const_lat_intersection
812±20ns 827±20ns 1.02 geometry_kernels.GCAConstLatIntersection.time_try_gca_const_lat_intersection
816±20ns 801±10ns 0.98 geometry_kernels.GCAGCAIntersection.time_accux_gca_kernel
932±20ns 902±40ns 0.97 geometry_kernels.GCAGCAIntersection.time_gca_gca_intersection
1.03±0.02μs 1.04±0.02μs 1.00 geometry_kernels.GCAGCAIntersection.time_try_gca_gca_intersection
50.7±2μs 51.5±3μs 1.01 geometry_kernels.OrientPredicates.time_on_minor_arc
50.9±1μs 51.2±3μs 1.01 geometry_kernels.OrientPredicates.time_orient3d_on_sphere
3.05±0ms 3.06±0ms 1.00 geometry_samebody.SameBodyConstLat.time_accux_dispatch
1.17±0ms 1.16±0ms 0.99 geometry_samebody.SameBodyConstLat.time_accux_kernel
2.31±0.01ms 2.28±0ms 0.99 geometry_samebody.SameBodyConstLat.time_fp64_dispatch
148±0.07μs 148±2μs 1.00 geometry_samebody.SameBodyConstLat.time_fp64_kernel
29.7±0.2ms 29.6±0.2ms 1.00 geometry_samebody_gcagca.SameBodyGcaGca.time_accux_dispatch
6.28±0.02ms 6.34±0.03ms 1.01 geometry_samebody_gcagca.SameBodyGcaGca.time_accux_kernel
23.6±0.1ms 23.7±0.03ms 1.01 geometry_samebody_gcagca.SameBodyGcaGca.time_fp64_dispatch
864±5μs 862±20μs 1.00 geometry_samebody_gcagca.SameBodyGcaGca.time_fp64_kernel
972±20ms 993±10ms 1.02 import.Imports.timeraw_import_uxarray
2.52±0.08ms 2.50±0.03ms 0.99 mpas_ocean.CheckNorm.time_check_norm('120km')
1.99±0.01ms 2.01±0.05ms 1.01 mpas_ocean.CheckNorm.time_check_norm('480km')
1.12±0.01ms 1.15±0.03ms 1.03 mpas_ocean.ConnectivityConstruction.time_face_face_connectivity('120km')
562±7μs 535±9μs 0.95 mpas_ocean.ConnectivityConstruction.time_face_face_connectivity('480km')
655±5μs 658±4μs 1.01 mpas_ocean.ConnectivityConstruction.time_n_nodes_per_face('120km')
585±10μs 605±10μs 1.04 mpas_ocean.ConnectivityConstruction.time_n_nodes_per_face('480km')
5.31±0.03ms 5.29±0.01ms 1.00 mpas_ocean.ConstructFaceLatLon.time_cartesian_averaging('120km')
3.87±0.06ms 3.85±0.01ms 0.99 mpas_ocean.ConstructFaceLatLon.time_cartesian_averaging('480km')
96.4±0.1ms 96.9±0.1ms 1.00 mpas_ocean.ConstructFaceLatLon.time_welzl('120km')
9.44±0.07ms 9.65±0.3ms 1.02 mpas_ocean.ConstructFaceLatLon.time_welzl('480km')
18.7±0.09ms 18.8±0.1ms 1.01 mpas_ocean.ConstructTreeStructures.time_ball_tree('120km')
969±20μs 989±10μs 1.02 mpas_ocean.ConstructTreeStructures.time_ball_tree('480km')
10.0±0.04ms 9.96±0.04ms 0.99 mpas_ocean.ConstructTreeStructures.time_kd_tree('120km')
607±10μs 621±9μs 1.02 mpas_ocean.ConstructTreeStructures.time_kd_tree('480km')
595±0.7ms 615±6ms 1.03 mpas_ocean.CrossSections.time_const_lat('120km', 1)
301±1ms 302±0.8ms 1.00 mpas_ocean.CrossSections.time_const_lat('120km', 2)
155±0.6ms 156±0.6ms 1.01 mpas_ocean.CrossSections.time_const_lat('120km', 4)
545±4ms 554±10ms 1.02 mpas_ocean.CrossSections.time_const_lat('480km', 1)
281±2ms 284±2ms 1.01 mpas_ocean.CrossSections.time_const_lat('480km', 2)
141±3ms 140±0.6ms 1.00 mpas_ocean.CrossSections.time_const_lat('480km', 4)
342M 366M 1.07 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('120km', 1)
346M 366M 1.06 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('120km', 2)
342M 366M 1.07 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('120km', 4)
26.9±0.05ms 26.5±0.06ms 0.99 mpas_ocean.DualMesh.time_dual_mesh_construction('120km')
2.98±0.01ms 2.91±0.01ms 0.98 mpas_ocean.DualMesh.time_dual_mesh_construction('480km')
14.8±0.7ms 14.9±0.7ms 1.01 mpas_ocean.FaceAreas.time_face_areas('120km')
4.40±0.08ms 4.44±0.2ms 1.01 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')
719k 719k 1.00 mpas_ocean.FaceAreas.track_peakmem_face_areas('480km')
323±3ms 329±3ms 1.02 mpas_ocean.GeoDataFrame.time_to_geodataframe('120km', False)
49.9±0.6ms 54.1±0.7ms 1.08 mpas_ocean.GeoDataFrame.time_to_geodataframe('120km', True)
43.5±0.8ms 42.4±0.9ms 0.97 mpas_ocean.GeoDataFrame.time_to_geodataframe('480km', False)
4.95±0.2ms 5.17±0.1ms 1.04 mpas_ocean.GeoDataFrame.time_to_geodataframe('480km', True)
13.1±0.07ms 13.2±0.06ms 1.00 mpas_ocean.Gradient.time_gradient('120km')
1.81±0.01ms 1.81±0.01ms 1.00 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.2M 3.2M 1.00 mpas_ocean.Gradient.track_peakmem_gradient('120km')
204k 204k 1.00 mpas_ocean.Gradient.track_peakmem_gradient('480km')
338M 366M 1.08 mpas_ocean.GradientColdStartRss.track_peakmem_gradient('120km')
286±10μs 277±8μs 0.97 mpas_ocean.HoleEdgeIndices.time_construct_hole_edge_indices('120km')
151±10μs 147±1μs 0.97 mpas_ocean.HoleEdgeIndices.time_construct_hole_edge_indices('480km')
200±9μs 204±10μs 1.02 mpas_ocean.Integrate.time_integrate('120km')
186±2μs 186±2μs 1.00 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')
184±3ms 184±0.4ms 1.00 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'exclude')
183±1ms 186±2ms 1.02 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'include')
184±2ms 184±0.8ms 1.00 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('120km', 'split')
12.8±0.06ms 13.1±0.1ms 1.03 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'exclude')
12.8±0.06ms 13.0±0.2ms 1.02 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'include')
12.8±0.09ms 13.0±0.1ms 1.01 mpas_ocean.MatplotlibConversion.time_dataarray_to_polycollection('480km', 'split')
251±0.3ms 248±1ms 0.99 mpas_ocean.NeighborhoodBuild.time_build('120km', 1.0)
540±20ms 510±3ms 0.94 mpas_ocean.NeighborhoodBuild.time_build('120km', 5.0)
13.7±0.03ms 13.9±0.07ms 1.01 mpas_ocean.NeighborhoodBuild.time_build('480km', 1.0)
18.0±0.8ms 16.9±0.09ms 0.94 mpas_ocean.NeighborhoodBuild.time_build('480km', 5.0)
243±0.9ms 245±4ms 1.01 mpas_ocean.NeighborhoodBuild.time_query_radius('120km', 1.0)
504±4ms 511±5ms 1.01 mpas_ocean.NeighborhoodBuild.time_query_radius('120km', 5.0)
13.1±0.08ms 13.3±0.1ms 1.02 mpas_ocean.NeighborhoodBuild.time_query_radius('480km', 1.0)
16.1±0.1ms 16.5±0.09ms 1.02 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)
825k 825k 1.00 mpas_ocean.NeighborhoodBuild.track_peakmem_build('480km', 15.0)
384k 384k 1.00 mpas_ocean.NeighborhoodBuild.track_peakmem_build('480km', 5.0)
41.4±0.5ms 41.6±0.1ms 1.00 mpas_ocean.NeighborhoodDask.time_mean('120km', 'grid_chunks')
18.7±0.07ms 18.5±0.1ms 0.99 mpas_ocean.NeighborhoodDask.time_mean('120km', 'numpy')
37.2±0.6ms 37.2±0.6ms 1.00 mpas_ocean.NeighborhoodDask.time_mean('120km', 'time_chunks')
11.7±0.1ms 11.7±0.1ms 1.01 mpas_ocean.NeighborhoodDask.time_mean('480km', 'grid_chunks')
756±10μs 744±8μs 0.98 mpas_ocean.NeighborhoodDask.time_mean('480km', 'numpy')
7.94±0.03ms 8.06±0.3ms 1.01 mpas_ocean.NeighborhoodDask.time_mean('480km', 'time_chunks')
5.83M 5.82M 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.68M 5.68M 1.00 mpas_ocean.NeighborhoodDask.track_peakmem_mean('120km', 'time_chunks')
757k 691k 0.91 mpas_ocean.NeighborhoodDask.track_peakmem_mean('480km', 'grid_chunks')
177k 177k 1.00 mpas_ocean.NeighborhoodDask.track_peakmem_mean('480km', 'numpy')
538k 538k 1.00 mpas_ocean.NeighborhoodDask.track_peakmem_mean('480km', 'time_chunks')
4.51±0.01s 4.50±0.01s 1.00 mpas_ocean.NeighborhoodReduce.time_dataset_reduce('120km', 'mean')
4.61±0.01s 4.62±0.01s 1.00 mpas_ocean.NeighborhoodReduce.time_dataset_reduce('120km', 'median')
122±0.3ms 123±0.5ms 1.00 mpas_ocean.NeighborhoodReduce.time_dataset_reduce('480km', 'mean')
126±0.4ms 126±0.8ms 1.00 mpas_ocean.NeighborhoodReduce.time_dataset_reduce('480km', 'median')
512±2ms 509±3ms 0.99 mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('120km', 'mean')
540±1ms 544±1ms 1.01 mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('120km', 'median')
16.8±0.08ms 16.7±0.05ms 1.00 mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('480km', 'mean')
17.1±0.08ms 17.0±0.02ms 1.00 mpas_ocean.NeighborhoodReduce.time_neighborhood_reduce('480km', 'median')
4.49±0.01ms 4.56±0.04ms 1.02 mpas_ocean.NeighborhoodReduce.time_reduce('120km', 'mean')
37.2±0.3ms 37.6±0.04ms 1.01 mpas_ocean.NeighborhoodReduce.time_reduce('120km', 'median')
243±10μs 242±3μs 0.99 mpas_ocean.NeighborhoodReduce.time_reduce('480km', 'mean')
535±9μs 559±10μs 1.04 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.5k 19.5k 1.00 mpas_ocean.NeighborhoodReduce.track_peakmem_reduce('480km', 'median')
420±20μs 445±50μs 1.06 mpas_ocean.PointInPolygon.time_face_search_lonlat('120km')
401±40μs 411±50μs 1.02 mpas_ocean.PointInPolygon.time_face_search_lonlat('480km')
454±30μs 422±20μs 0.93 mpas_ocean.PointInPolygon.time_face_search_xyz('120km')
356±20μs 400±30μs ~1.12 mpas_ocean.PointInPolygon.time_face_search_xyz('480km')
108±0.8ms 112±0.7ms 1.03 mpas_ocean.RemapDownsample.time_bilinear_remapping
17.3±0.3ms 17.2±0.1ms 1.00 mpas_ocean.RemapDownsample.time_inverse_distance_weighted_remapping
15.4±0.09ms 15.5±0.1ms 1.01 mpas_ocean.RemapDownsample.time_nearest_neighbor_remapping
1.10±0.02s 1.11±0.01s 1.00 mpas_ocean.RemapUpsample.time_bilinear_remapping
26.2±0.2ms 29.3±3ms ~1.12 mpas_ocean.RemapUpsample.time_inverse_distance_weighted_remapping
11.6±0.2ms 11.8±0.1ms 1.01 mpas_ocean.RemapUpsample.time_nearest_neighbor_remapping
8.38±0.1ms 8.39±0.1ms 1.00 mpas_ocean.ZonalAverage.time_zonal_average('120km')
5.28±0.05ms 5.31±0.1ms 1.01 mpas_ocean.ZonalAverage.time_zonal_average('480km')
343M 367M 1.07 mpas_ocean.ZonalAveragePeakMem.track_peakmem_zonal_average('120km')
1.0472665481500785 1.0409985720677712 0.99 nogil_scaling.GILScaling.track_gil_scaling
8.19±0.8ms 8.33±0.1ms 1.02 quad_hexagon.QuadHexagon.time_open_dataset
6.60±0.3ms 7.06±0.3ms 1.07 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
73.5k 72.5k 0.99 quad_hexagon.QuadHexagon.track_peakmem_open_dataset
72.7k 71.6k 0.99 quad_hexagon.QuadHexagon.track_peakmem_open_grid
1.11±0.01s 1.12±0s 1.01 to_raster.ToRaster.time_to_raster((10000.0, 10.0))
2.72±0s 2.70±0.02s 0.99 to_raster.ToRaster.time_to_raster((10000.0, 100.0))
3.09±0s 3.10±0.02s 1.00 to_raster.ToRaster.time_to_raster((100000.0, 100.0))
271M 271M 1.00 to_raster.ToRaster.track_peakmem((10000.0, 10.0))
684M 684M 1.00 to_raster.ToRaster.track_peakmem((10000.0, 100.0))
768M 768M 1.00 to_raster.ToRaster.track_peakmem((100000.0, 100.0))

Benchmarks that have got worse:

Change Before [03cb40d] After [32a4fb1] Ratio Benchmark (Parameter)
+ 321M 366M 1.14 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/mpas/QU/oQU480.231010.nc'))
+ 322M 366M 1.14 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/scrip/outCSne8/outCSne8.nc'))
+ 323M 366M 1.13 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/geoflow-small/grid.nc'))
+ 323M 366M 1.14 face_bounds.FaceBoundsColdStartRss.track_peakmem_open_and_bounds(PosixPath('/home/runner/work/uxarray/uxarray/test/meshfiles/ugrid/quad-hexagon/grid.nc'))
+ 280M 366M 1.31 import.Imports.track_peakmem_import_uxarray
+ 325M 366M 1.13 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('480km', 1)
+ 325M 366M 1.13 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('480km', 2)
+ 325M 366M 1.13 mpas_ocean.CrossSectionsPeakMem.track_peakmem_const_lat('480km', 4)
+ 317M 366M 1.16 mpas_ocean.GradientColdStartRss.track_peakmem_gradient('480km')
+ 326M 367M 1.13 mpas_ocean.ZonalAveragePeakMem.track_peakmem_zonal_average('480km')

cmdupuis3 and others added 4 commits September 30, 2026 14:08
… Numba

The robust path built several tiny polars DataFrames per candidate face,
and that fixed per-call overhead was nearly its whole runtime. Each
latitude is now two Numba calls: one computing every candidate face's
longitude intervals, and one running the overlap sweep line. Results are
bit-identical, and robust zonal means are 52-86x faster, now within
1.3-2.7x of the default path instead of 100-200x slower.

Both new per-latitude kernels release the GIL. Each call does milliseconds
of work, so from 4 threads the robust weights take 1.09x the single-thread
wall time instead of 4.03x.

The private helpers now use arrays instead of DataFrames:
_zonal_face_weights_robust returns the weights, _get_zonal_face_interval
returns (start, end) rows, and _process_overlapped_intervals takes
starts/ends/face indices and returns per-face contributions. A face whose
crossing longitudes cannot be paired into intervals now raises ValueError
rather than polars' ShapeError.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-benchmark Run ASV benchmark workflow scalability Related to scalability & performance efforts

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unoptimized routines in integrate.py

1 participant