-
Notifications
You must be signed in to change notification settings - Fork 680
[DON'T MERGE] FOEPD-1977: Move label post-processing to background thread #6307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -485,8 +485,17 @@ def _apply_image_model_data_loader( | |
| warning="Async failure labeling batches", | ||
| ) | ||
| ) | ||
| output_processor = getattr( | ||
| model, "_output_processor", lambda output, *_, **__: output | ||
| ) | ||
| context.enter_context(fou.SetAttributes(model, _output_processor=None)) | ||
|
|
||
| def save_batch(sample_batch, labels_batch): | ||
| def save_batch(sample_batch, output, image_sizes): | ||
| labels_batch = output_processor( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is it actually more efficient to do this in a thread? How do the size of the output vectors compare to the final predicted objects?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not more efficient, it's more concurrent. Moving this to a background thread allows the output to be processed while the next batch's inputs are being processed and run. I.e. (not to scale) gantt
title Async postprocessing
dateFormat X
axisFormat %s
section Main thread
Preprocess :active, preprocess, 0, 1
Predict :active, predict, 1, 2
Preprocess :active, preprocess, 2, 3
Predict :active, predict, 3, 4
section Background thread
Postprocess :active, postprocess, 2, 3
Write :active, write, 3, 4
Postprocess :active, postprocess, 4, 5
Write :active, write, 5, 6
With the test script, |
||
| output, | ||
| image_sizes, | ||
| confidence_thresh=model.config.confidence_thresh, | ||
| ) | ||
| with _handle_batch_error(skip_failures, sample_batch): | ||
| for sample, labels in zip(sample_batch, labels_batch): | ||
| if filename_maker is not None: | ||
|
|
@@ -507,14 +516,15 @@ def save_batch(sample_batch, labels_batch): | |
| if isinstance(imgs, Exception): | ||
| raise imgs | ||
|
|
||
| image_sizes = imgs.pop("fo_image_size", [(None, None)]) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| if needs_samples: | ||
| labels_batch = model.predict_all( | ||
| imgs, samples=sample_batch | ||
| ) | ||
| output = model.predict_all(imgs, samples=sample_batch) | ||
| else: | ||
| labels_batch = model.predict_all(imgs) | ||
| output = model.predict_all(imgs) | ||
|
|
||
| submit(save_batch, sample_batch, labels_batch) | ||
| submit( | ||
| save_batch, sample_batch, output, image_sizes=image_sizes | ||
| ) | ||
|
|
||
| pb.update(len(sample_batch)) | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid mutating models that don’t define _output_processor; guard and fall back cleanly
Setting a private attribute on all models can change behavior inadvertently. Only disable
_output_processorwhen it exists; otherwise use a no-op postprocessor.📝 Committable suggestion
🤖 Prompt for AI Agents