streaming
sleap_nn.inference.streaming
¶
Streaming primitives for the new inference stack.
Two value types and one worker pool sit here so they can be imported
both by BottomUpLayer (which produces ScoredBatch on the GPU
side) and by the worker process (which consumes it).
- :class:
ScoredBatch— the picklable output of the GPU stage of bottom-up inference (peaks + line scores). Contains every tensor the CPU grouping stage needs and nothing more. - :class:
GroupingParams— the picklable layer-level configuration needed to convert a :class:ScoredBatchinto an :class:Outputs(PAFScorer kwargs, NaN-pad target,return_*flags). - :func:
group_scored_batch— the pure CPU function called inline or in a worker process. Reconstructs a :class:PAFScorerfrom the kwargs inGroupingParamsand runs match + group + NaN-pad + scale-correction. - :class:
PafGroupingPool— context-managedProcessPoolExecutorwrapper that submitsScoredBatchinstances and yields completedOutputsin submission order.
PR 9 (#517). The pool is opt-in via Predictor(paf_workers=N) —
N=0 keeps the inline single-process path (default, matches today).
Classes:
| Name | Description |
|---|---|
GroupingParams |
Layer-level params needed to turn a |
PafGroupingPool |
Multiprocessing pool for the CPU grouping stage of bottom-up. |
ScoredBatch |
GPU-stage output of bottom-up inference, ready for CPU grouping. |
Functions:
| Name | Description |
|---|---|
group_scored_batch |
Run the CPU grouping stage on a :class: |
GroupingParams
¶
Layer-level params needed to turn a ScoredBatch into Outputs.
Picklable (every field is a plain Python value or a small dict), so this can travel to a worker process by value.
Attributes:
| Name | Type | Description |
|---|---|---|
paf_scorer_kwargs |
dict
|
Kwargs for the :class: |
max_instances |
Optional[int]
|
Cap on instances per frame. When |
return_confmaps |
bool
|
Echo confmaps into |
return_pafs |
bool
|
Echo PAFs into |
return_paf_graph |
bool
|
Echo the per-batch PAF graph (peaks + edge
inds + edge peak inds + line scores) into
|
Source code in sleap_nn/inference/streaming.py
PafGroupingPool
¶
Multiprocessing pool for the CPU grouping stage of bottom-up.
Lifetime: a context manager. Use with PafGroupingPool(...) as pool.
Calls outside the with block raise — the executor is None.
Submission order is FIFO; results are yielded in submission order
(a future blocks iter_completed until earlier ones finish, which
matches the frame-ordering contract of Predictor outputs).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_workers
|
Number of worker processes. |
required | |
grouping_params
|
Layer-level params for the grouping function; shipped as a per-call argument so it remains picklable (the executor's submit copies it once per call but the data is small). |
required |
Notes
On macOS / Windows the pool uses spawn and each worker pays a
~1s startup cost. Users running on those platforms should
either keep the default paf_workers=0 for short videos or
size the pool small.
Methods:
| Name | Description |
|---|---|
__attrs_post_init__ |
Validate |
__enter__ |
Start the pool's worker processes. |
__exit__ |
Tear down workers; cancel pending futures on exception. |
__len__ |
Number of submitted-but-not-yet-drained batches (in-flight depth). |
drain_one |
Pop + block on the OLDEST pending batch (FIFO); |
iter_completed |
Drain all submitted batches, yielding |
submit |
Enqueue a :class: |
Source code in sleap_nn/inference/streaming.py
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | |
__attrs_post_init__()
¶
Validate n_workers.
__enter__()
¶
Start the pool's worker processes.
Always uses the spawn start method. ProcessPoolExecutor defaults
to fork on Linux, which inherits the parent's already-initialized
CUDA context and deadlocks the first worker call. spawn is the
same start method already used on macOS / Windows by default.
Source code in sleap_nn/inference/streaming.py
__exit__(exc_type, exc, tb)
¶
Tear down workers; cancel pending futures on exception.
Source code in sleap_nn/inference/streaming.py
__len__()
¶
drain_one()
¶
Pop + block on the OLDEST pending batch (FIFO); None if empty.
Lets a caller interleave submit and drain to bound the number of
in-flight batches (true O(window) streaming) while preserving the same
submission-order yield as :meth:iter_completed. Because submission is
sequential on the main thread, the oldest future is always real, so
this never deadlocks.
Source code in sleap_nn/inference/streaming.py
iter_completed()
¶
Drain all submitted batches, yielding (frame_idx, Outputs) in order.
Blocks on each future in submission order so the caller observes the same frame ordering as the inline path. Cleans the internal pending list as it goes.
Source code in sleap_nn/inference/streaming.py
submit(frame_idx, scored)
¶
Enqueue a :class:ScoredBatch for grouping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
frame_idx
|
int
|
Caller-supplied submission ordinal (0, 1, 2, ...);
used only for |
required |
scored
|
ScoredBatch
|
The GPU-stage payload. |
required |
Source code in sleap_nn/inference/streaming.py
ScoredBatch
¶
GPU-stage output of bottom-up inference, ready for CPU grouping.
Carries everything :func:group_scored_batch needs and nothing
more. Tensors should be detached + on CPU before this is shipped to
a worker (ProcessPoolExecutor pickles via shared-memory but a
GPU tensor in an off-process worker is undefined). The
:class:BottomUpLayer ensures CPU residency before submission.
Attributes:
| Name | Type | Description |
|---|---|---|
cms_peaks |
List[Tensor]
|
Per-sample list of |
cms_peak_vals |
List[Tensor]
|
Per-sample list of |
cms_peak_channel_inds |
List[Tensor]
|
Per-sample list of |
edge_inds |
List[Tensor]
|
Per-sample list of |
edge_peak_inds |
List[Tensor]
|
Per-sample list of |
line_scores |
List[Tensor]
|
Per-sample list of |
info |
PreprocInfo
|
The :class: |
n_samples |
int
|
Batch size; cached for cheap unpacking. |
n_nodes |
int
|
Number of nodes in the skeleton. |
skip_paf |
bool
|
|
cms |
Optional[Tensor]
|
Optional confmaps tensor for |
pafs |
Optional[Tensor]
|
Optional PAFs tensor for |
Methods:
| Name | Description |
|---|---|
to_cpu |
Detach + move every tensor field to CPU (idempotent on CPU). |
Source code in sleap_nn/inference/streaming.py
to_cpu()
¶
Detach + move every tensor field to CPU (idempotent on CPU).
Includes info.eff_scale, which is a device-resident tensor on
cuda/mps after PR 26 made layer preprocess buffers device-aware.
Pre-PR-26 eff_scale was always CPU so the original to_cpu
ignored info; that assumption silently broke worker-pool
submissions on CUDA (spawn can't unpickle a CUDA tensor without
a shared CUDA context → deadlock on ProcessPoolExecutor.submit).
Source code in sleap_nn/inference/streaming.py
group_scored_batch(scored, params)
¶
Run the CPU grouping stage on a :class:ScoredBatch.
This is the worker entry point for :class:PafGroupingPool and
also the function that :class:BottomUpLayer.postprocess calls
inline so the two paths share one source of truth. Pure CPU,
no autograd, no model state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scored
|
ScoredBatch
|
Output of the GPU stage (peaks + scored PAF lines). |
required |
params
|
GroupingParams
|
Layer-level grouping configuration. |
required |
Returns:
| Type | Description |
|---|---|
Outputs
|
The per-batch :class: |
Source code in sleap_nn/inference/streaming.py
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | |