feat(perception): prewarm RF-DETR before source admission
This commit is contained in:
@@ -101,6 +101,31 @@ class DetectorFrameTiming:
|
||||
DetectorTimingObserver = Callable[[DetectorFrameTiming], None]
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class DetectorWarmupSnapshot:
|
||||
completed: bool
|
||||
inference_passes: int
|
||||
preprocess_duration_ns: int
|
||||
inference_transport_duration_ns: int
|
||||
postprocess_duration_ns: int
|
||||
total_duration_ns: int
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
durations = (
|
||||
self.preprocess_duration_ns,
|
||||
self.inference_transport_duration_ns,
|
||||
self.postprocess_duration_ns,
|
||||
self.total_duration_ns,
|
||||
)
|
||||
if (
|
||||
self.completed is not True
|
||||
or self.inference_passes != 1
|
||||
or any(value < 0 for value in durations)
|
||||
or sum(durations[:3]) != self.total_duration_ns
|
||||
):
|
||||
raise DetectorProviderError("detector warmup snapshot is incompatible")
|
||||
|
||||
|
||||
class FrozenYoloxDetectorProvider:
|
||||
"""One image payload produces one frozen inference request and proposal tuple."""
|
||||
|
||||
@@ -259,6 +284,50 @@ class RfDetrShadowDetectorProvider:
|
||||
self._proposal_count = 0
|
||||
self._rejected: Counter[str] = Counter()
|
||||
self._core_duration_ns = 0
|
||||
self._warmup_started = False
|
||||
self._warmup_snapshot: DetectorWarmupSnapshot | None = None
|
||||
|
||||
def warm_up(self) -> DetectorWarmupSnapshot:
|
||||
"""Prime preprocessing, transport and postprocessing before source admission."""
|
||||
|
||||
with self._lock:
|
||||
if self._warmup_snapshot is not None:
|
||||
return self._warmup_snapshot
|
||||
if self._warmup_started:
|
||||
raise DetectorProviderError("RF-DETR warmup is already in progress")
|
||||
self._warmup_started = True
|
||||
started_ns = int(self._clock_ns())
|
||||
try:
|
||||
image = np.zeros(
|
||||
(self.config.source_height, self.config.source_width, 3),
|
||||
dtype=np.uint8,
|
||||
)
|
||||
tensor = preprocess_raw_kb4_rf_detr(
|
||||
image,
|
||||
self.mask,
|
||||
config=self.config,
|
||||
resizer=self.resizer,
|
||||
)
|
||||
preprocessed_ns = int(self._clock_ns())
|
||||
output = self.backend.infer(tensor)
|
||||
inferred_ns = int(self._clock_ns())
|
||||
postprocess_rf_detr(output, self.mask, config=self.config)
|
||||
completed_ns = int(self._clock_ns())
|
||||
except Exception:
|
||||
with self._lock:
|
||||
self._warmup_started = False
|
||||
raise
|
||||
snapshot = DetectorWarmupSnapshot(
|
||||
completed=True,
|
||||
inference_passes=1,
|
||||
preprocess_duration_ns=max(0, preprocessed_ns - started_ns),
|
||||
inference_transport_duration_ns=max(0, inferred_ns - preprocessed_ns),
|
||||
postprocess_duration_ns=max(0, completed_ns - inferred_ns),
|
||||
total_duration_ns=max(0, completed_ns - started_ns),
|
||||
)
|
||||
with self._lock:
|
||||
self._warmup_snapshot = snapshot
|
||||
return snapshot
|
||||
|
||||
def detect(self, packet: SourcePacket) -> tuple[ObjectProposal2D, ...]:
|
||||
payload = packet.image_payload
|
||||
@@ -357,6 +426,7 @@ __all__ = [
|
||||
"DetectorProviderSnapshot",
|
||||
"DetectorFrameTiming",
|
||||
"DetectorTimingObserver",
|
||||
"DetectorWarmupSnapshot",
|
||||
"AllCocoYoloxDetectorProvider",
|
||||
"FrozenYoloxDetectorProvider",
|
||||
"RfDetrShadowDetectorProvider",
|
||||
|
||||
Reference in New Issue
Block a user