Rendre la carte autonome, télécharger la pyramide en fond, refermer les trous de zoom et borner les workers GPU par la VRAM

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Antoine Jacquin
2026-09-27 11:23:51 +02:00
parent 934e2dab55
commit 147a469ddc
10 changed files with 586 additions and 37 deletions

View File

@ -199,4 +199,57 @@ def test_safe_gpu_call_retries_on_cpu_for_any_error(monkeypatch):
gpu.safe_gpu_call(g, 1)
raise AssertionError("devait relancer l'erreur")
except ValueError:
pass
pass
def test_gpu_worker_slots_bounded_by_free_vram(monkeypatch):
"""Places GPU par la VRAM libre : l'excédent de workers passe en CPU.
Cas réel : LIDAR_WORKERS=auto = 12 workers sur 2 RTX 5060 (8 Go) —
6 workers par GPU, soit bien plus que la VRAM libre ne tient au pic
(calage des lignes + comblement GPU) : OOM.
"""
from lidar_pipeline import gpu
monkeypatch.setattr(gpu, "GPU_WORKER_MIB", 2000)
monkeypatch.setattr(gpu, "GPU_RESERVE_MIB", 500)
free = {0: 7500, 1: 4600}
slots = gpu.gpu_worker_slots([0, 1], 12, free_mib=free)
assert len(slots) == 12
assert slots.count(0) == 3 # (7500 - 500) // 2000
assert slots.count(1) == 2 # (4600 - 500) // 2000
assert slots.count(-1) == 7 # reste en CPU
# GPU d'abord, entrelacés : les premiers workers créés se répartissent
assert slots[:4] == [0, 1, 0, 1]
# Moins de workers que de places : aucun CPU forcé
assert gpu.gpu_worker_slots([0, 1], 3, free_mib=free) == [0, 1, 0]
def test_gpu_worker_slots_without_gpu_or_vram_info():
"""Sans GPU : tout en CPU implicite (None). VRAM inconnue : round-robin
historique (pas de bornage sans mesure)."""
from lidar_pipeline import gpu
assert gpu.gpu_worker_slots([], 4, free_mib={}) == [None] * 4
assert gpu.gpu_worker_slots([0, 1], 4, free_mib={}) == [0, 1, 0, 1]
def test_gpu_worker_slots_keeps_one_gpu_worker_when_tight(monkeypatch):
"""GPU presque plein : au moins une place pour que le GPU serve encore
(le repli CPU de safe_gpu_call couvre l'OOM éventuel)."""
from lidar_pipeline import gpu
monkeypatch.setattr(gpu, "GPU_WORKER_MIB", 2000)
monkeypatch.setattr(gpu, "GPU_RESERVE_MIB", 500)
assert gpu.gpu_worker_slots([0], 3, free_mib={0: 900}) == [0, -1, -1]
def test_force_cpu_disables_gpu_selection(monkeypatch):
"""force_cpu() : aucun candidat GPU, CuPy jamais initialisé."""
import os
from lidar_pipeline import gpu
monkeypatch.setattr(gpu, "_restricted_gpu_ids", None)
monkeypatch.setattr(gpu, "_gpu_candidates", [(0, "X", "12.0", 8000, 1, 12)])
monkeypatch.setattr(gpu, "_gpu_initialized", False)
monkeypatch.setattr(gpu, "_env_set_by_init", False)
monkeypatch.delenv("CUDA_VISIBLE_DEVICES", raising=False)
gpu.force_cpu()
assert gpu.available_gpu_ids() == []
assert gpu.HAS_GPU is False
assert os.environ.get("CUDA_VISIBLE_DEVICES") == ""