Skip to content

Commit 27d6771

Browse files
committed
Address review: select on the running best, larger concurrency raster (#3740)
Update best_dist only when the candidate wins so a NaN rounded distance (a haversine term a hair past 1.0) is skipped instead of poisoning every later comparison, as the old kernel did. Comment the placeholder great circle arrays on the non-great-circle call path. Hammer the lock test with a 40x40 raster so the concurrent launches overlap.
1 parent fc27112 commit 27d6771

2 files changed

Lines changed: 15 additions & 6 deletions

File tree

xrspatial/proximity.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,9 @@ def _collect_targets(img, target_values):
540540
# comment in ``_proximity_cuda_kernel``). A candidate whose proxy does not
541541
# beat the running best has a float32 distance >= the running best and could
542542
# never have won under that rule, so skipping it changes nothing.
543+
# The running best is updated with a select rather than a branch, and only
544+
# when the candidate wins, so a NaN distance (say a haversine term rounded a
545+
# hair past 1.0) is skipped instead of poisoning every later comparison.
543546

544547
@ngjit
545548
def _nearest_euclidean(px, py, txs, tys):
@@ -554,7 +557,7 @@ def _nearest_euclidean(px, py, txs, tys):
554557
d = np.float32(np.sqrt(proxy))
555558
better = d < best_dist
556559
best_idx = k if better else best_idx
557-
best_dist = d
560+
best_dist = d if better else best_dist
558561
best_proxy = proxy
559562
return best_idx, best_dist
560563

@@ -572,7 +575,7 @@ def _nearest_manhattan(px, py, txs, tys):
572575
d = np.float32(proxy)
573576
better = d < best_dist
574577
best_idx = k if better else best_idx
575-
best_dist = d
578+
best_dist = d if better else best_dist
576579
best_proxy = proxy
577580
return best_idx, best_dist
578581

@@ -596,7 +599,7 @@ def _nearest_great_circle(px, py, tlons, tlats, tcoslats):
596599
d = np.float32(6378137 * 2 * np.arcsin(np.sqrt(proxy)))
597600
better = d < best_dist
598601
best_idx = k if better else best_idx
599-
best_dist = d
602+
best_dist = d if better else best_dist
600603
best_proxy = proxy
601604
return best_idx, best_dist
602605

@@ -729,6 +732,7 @@ def _process_numpy_bruteforce(
729732
raise ValueError(_GREAT_CIRCLE_RANGE_MESSAGES[violation])
730733
tlons, tlats, tcoslats = _great_circle_target_terms(txs, tys)
731734
else:
735+
# Placeholders: the kernel only reads these under GREAT_CIRCLE.
732736
tlons = tlats = tcoslats = np.empty(0, dtype=np.float64)
733737

734738
with _PARALLEL_KERNEL_LOCK:

xrspatial/tests/test_proximity.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -825,11 +825,16 @@ def test_bruteforce_concurrent_launches_match_serial():
825825
# pool and check every caller gets the single-threaded answer.
826826
from concurrent.futures import ThreadPoolExecutor
827827

828-
raster = _simple_raster()
829-
expected = allocation(raster, x='lon', y='lat').data
828+
# Use a raster large enough that the launches actually overlap.
829+
data = np.zeros((40, 40), dtype=np.float64)
830+
rng = np.random.default_rng(3740)
831+
data.flat[rng.choice(data.size, 50, replace=False)] = rng.integers(
832+
1, 6, 50)
833+
raster = create_test_raster(data, backend='numpy')
834+
expected = allocation(raster).data
830835

831836
def one(_):
832-
return allocation(raster, x='lon', y='lat').data
837+
return allocation(raster).data
833838

834839
with ThreadPoolExecutor(max_workers=8) as pool:
835840
results = list(pool.map(one, range(32)))

0 commit comments

Comments
 (0)