Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/sweep-benchmarks-state.csv
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
module,last_inspected,issue,severity_max,categories_found,notes
geotiff,2026-07-02,3603,HIGH,1;2,"No benchmark existed for geotiff; open_geotiff/to_geotiff had zero asv coverage across numpy/dask/cupy. Added benchmarks/benchmarks/geotiff.py: WriteGeoTIFF (numpy/dask/cupy streaming), WriteCOG (numpy/cupy overview pyramid), ReadGeoTIFF (numpy/cupy decode), ReadGeoTIFFChunked (dask). All classes executed locally via direct call; cupy paths run on this GPU host. asv check discover fails suite-wide from an asv_runner + py3.14 metadata bug, unrelated to this file."
pathfinding,2026-07-08,3645,HIGH,1;2;3,"Bench covered only numpy a_star_search at nx<=300; module also ships dask (separate sparse-Python A* + LRU chunk cache), cupy fallback, and public multi_stop_search with zero coverage. Extended AStarSearch to numpy/cupy/dask with nx up to 1000 (dask capped at 300, ~4s/call at 1000) and added MultiStopSearch (ordered + optimize_order). All combos executed locally incl. cupy (GPU host). LOW noted, not fixed: open-grid no-barrier/no-friction input is A* best case. dask+cupy not parameterized anywhere in suite (common.get_xr_dataarray has no such type). Existing bench imports/runs fine (Cat 4 clean)."
37 changes: 34 additions & 3 deletions benchmarks/benchmarks/pathfinding.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,52 @@
from xrspatial.pathfinding import a_star_search
from xrspatial.pathfinding import a_star_search, multi_stop_search

from .common import get_xr_dataarray


class AStarSearch:
params = ([10, 100, 300], [4, 8], ["numpy"])
params = ([100, 300, 1000], [4, 8], ["numpy", "cupy", "dask"])
param_names = ("nx", "connectivity", "type")

def setup(self, nx, connectivity, type):
if type == "dask" and nx > 300:
# The dask backend is a pure-Python sparse A* that loads
# chunks on demand; at nx=1000 a single call takes ~4 s,
# which would dominate the suite's runtime.
raise NotImplementedError()
ny = nx // 2
self.agg = get_xr_dataarray((ny, nx), type)
self.start = self.agg.y[0], self.agg.x[0]
self.goal = self.agg.y[-1], self.agg.x[-1]
# snap_start/snap_goal raise on dask-backed arrays by design
self.snap = type != "dask"

def time_a_star_search(self, nx, connectivity, type):
a_star_search(
self.agg, self.start, self.goal,
connectivity=connectivity,
snap_start=True, snap_goal=True
snap_start=self.snap, snap_goal=self.snap
)


class MultiStopSearch:
params = ([100, 300], ["numpy", "cupy", "dask"])
param_names = ("nx", "type")

def setup(self, nx, type):
ny = nx // 2
self.agg = get_xr_dataarray((ny, nx), type)
ys = self.agg.y.data
xs = self.agg.x.data
# 4 waypoints zigzagging across the grid (3 segments)
self.waypoints = [
(ys[0], xs[0]),
(ys[-1], xs[nx // 3]),
(ys[0], xs[2 * nx // 3]),
(ys[-1], xs[-1]),
]

def time_multi_stop_search(self, nx, type):
multi_stop_search(self.agg, self.waypoints)

def time_multi_stop_search_optimize_order(self, nx, type):
multi_stop_search(self.agg, self.waypoints, optimize_order=True)
Loading