Fix ray-tracing OOM + NO_BINARY: pad DEM on CPU, free GPU intermediates
This commit is contained in:
@ -298,6 +298,11 @@ def _ray_trace_horizons(dem, rows, cols, res, n_dirs, max_dist, radii_m=None):
|
||||
recording the max upward angle (positive openness) and max downward angle
|
||||
(negative openness) reached at each radius checkpoint.
|
||||
|
||||
Padding is done on CPU (numpy) to avoid GPU memory pressure and
|
||||
pre-compiled kernel mismatches (CUDA_ERROR_NO_BINARY_FOR_GPU on sm_89).
|
||||
The padded array is transferred to GPU once, then each direction is
|
||||
processed and results are streamed back to CPU.
|
||||
|
||||
Args:
|
||||
dem: GPU or CPU filled DEM array (rows, cols).
|
||||
rows, cols: dimensions.
|
||||
@ -322,7 +327,15 @@ def _ray_trace_horizons(dem, rows, cols, res, n_dirs, max_dist, radii_m=None):
|
||||
radii_steps = [max_dist]
|
||||
n_radii = 1
|
||||
|
||||
padded = xp.pad(dem, max_dist, mode='constant', constant_values=xp.nan)
|
||||
# Pad on CPU (numpy) — avoids GPU memory pressure and
|
||||
# pre-compiled kernel issues (NO_BINARY_FOR_GPU on sm_89).
|
||||
dem_np = to_cpu(dem)
|
||||
padded_np = np.pad(dem_np, max_dist, mode='constant', constant_values=np.nan)
|
||||
|
||||
# Transfer padded DEM to GPU for computation
|
||||
padded = to_gpu(padded_np)
|
||||
# Free the CPU copy — we don't need it anymore
|
||||
del dem_np, padded_np
|
||||
|
||||
# Process one direction at a time to limit GPU memory.
|
||||
# Store results as flat CPU arrays — transfer back to GPU at the end.
|
||||
@ -349,13 +362,17 @@ def _ray_trace_horizons(dem, rows, cols, res, n_dirs, max_dist, radii_m=None):
|
||||
radii_remaining = set(range(n_radii))
|
||||
|
||||
for step, px, py, dist_m in valid_steps:
|
||||
elev_diff = padded[max_dist + py:max_dist + py + rows,
|
||||
max_dist + px:max_dist + px + cols] - dem
|
||||
# Slice from padded array, subtract original dem
|
||||
view = padded[max_dist + py:max_dist + py + rows,
|
||||
max_dist + px:max_dist + px + cols]
|
||||
elev_diff = view - dem
|
||||
del view # free slice reference
|
||||
|
||||
# Positive: angle to terrain above viewer
|
||||
pos_angle = xp.arctan2(xp.maximum(elev_diff, 0), dist_m)
|
||||
# Negative: angle to terrain below viewer
|
||||
neg_angle = xp.arctan2(xp.maximum(-elev_diff, 0), dist_m)
|
||||
del elev_diff # free intermediate
|
||||
|
||||
# Update running max for all radius checkpoints still active
|
||||
for r_idx in radii_remaining:
|
||||
|
||||
Reference in New Issue
Block a user