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
|
recording the max upward angle (positive openness) and max downward angle
|
||||||
(negative openness) reached at each radius checkpoint.
|
(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:
|
Args:
|
||||||
dem: GPU or CPU filled DEM array (rows, cols).
|
dem: GPU or CPU filled DEM array (rows, cols).
|
||||||
rows, cols: dimensions.
|
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]
|
radii_steps = [max_dist]
|
||||||
n_radii = 1
|
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.
|
# Process one direction at a time to limit GPU memory.
|
||||||
# Store results as flat CPU arrays — transfer back to GPU at the end.
|
# 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))
|
radii_remaining = set(range(n_radii))
|
||||||
|
|
||||||
for step, px, py, dist_m in valid_steps:
|
for step, px, py, dist_m in valid_steps:
|
||||||
elev_diff = padded[max_dist + py:max_dist + py + rows,
|
# Slice from padded array, subtract original dem
|
||||||
max_dist + px:max_dist + px + cols] - 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
|
# Positive: angle to terrain above viewer
|
||||||
pos_angle = xp.arctan2(xp.maximum(elev_diff, 0), dist_m)
|
pos_angle = xp.arctan2(xp.maximum(elev_diff, 0), dist_m)
|
||||||
# Negative: angle to terrain below viewer
|
# Negative: angle to terrain below viewer
|
||||||
neg_angle = xp.arctan2(xp.maximum(-elev_diff, 0), dist_m)
|
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
|
# Update running max for all radius checkpoints still active
|
||||||
for r_idx in radii_remaining:
|
for r_idx in radii_remaining:
|
||||||
|
|||||||
Reference in New Issue
Block a user