📦 WP-087d — perf(data): rasterise mask targets in the loader workers¶
Research log · Phase 7 — Instance segmentation, v0.2.0
🔗 Depends on WP-087c · Needed by none
WP-087d — rasterise mask targets in the loader workers¶
Vectorised, the rasterisation still sat between forward and loss — serial with the GPU and competing with the optimiser's dispatch loop for cores. Measured on COCO at batch 32 with mosaic on: 1,005 ms rasterising and 1,475 ms in an optimiser that costs 94 ms in isolation, the accelerator idle for most of a 2,250 ms step. The optimiser figure is the informative one: it is not slow, it is starved.
Moving the work into collate_detection puts it inside a DataLoader worker, so batches are rasterised concurrently and ahead of the step consuming them. Two design points that made it possible without handing the collate a model: the grid is the input canvas at a fixed stride of four, derivable because ProtoNet upsamples the stride-8 fused feature by two (A15); and masks travel as a bool (sum_N, Hp, Wp) stack split by boxes_per_image, exact because the values are {0,1} and a quarter the bytes.
That then put the collate on the critical path: 4,454 ms on one thread for 64 mosaic images carrying 2,170 instances — 2.09 s of a 3.04 s step in train_dataloader_next. Fixed by testing each ring only inside its own bounding window, which replaces 087c's flattened-edge batching rather than composing with it: sharing one grid across an image's instances is what made that bookkeeping worth carrying, and a window removes the shared grid.
| instance span | before | after |
|---|---|---|
| 30 px | 32.41 ms | 1.73 ms |
| 60 px | 35.00 ms | 3.27 ms |
| 120 px | 35.74 ms | 8.03 ms |
Cost now tracks the instance instead of being flat in the grid. Note the "before" column barely moves across a 4× span — that flatness is the defect, visible in the numbers before any explanation.
The correctness argument is stronger than "the window is large enough": outside it the crossing test is provably False rather than merely unlikely, and the window slices the coordinate ranges without translating the ring, so surviving pixels are bit-identical rather than equivalent.