fix(tilers): allow skipping expensive per-tile saliency map merge - #639
Closed
A-Artemis wants to merge 1 commit into
Closed
fix(tilers): allow skipping expensive per-tile saliency map merge#639A-Artemis wants to merge 1 commit into
A-Artemis wants to merge 1 commit into
Conversation
DetectionTiler._merge_saliency_maps merges per-tile saliency maps with a pure-Python, pixel-by-pixel nested loop (cost O(num_tiles * num_classes * H * W)). With the default tiling configuration (tile_size=400, tiles_overlap=0.5), a single large image can be split into hundreds of tiles, making that merge take minutes to hours for callers that never use the merged saliency map (e.g. when only computing detection accuracy metrics rather than an explanation). Add a merge_saliency_maps: bool = True constructor parameter/attribute to the base Tiler class (inherited by DetectionTiler and InstanceSegmentationTiler). When set to False, the expensive per-tile saliency merge is skipped entirely. It is a plain mutable attribute so callers can toggle it at any time, not just at construction. Defaults to True, preserving existing behavior.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds a merge_saliency_maps: bool = True constructor parameter/attribute to the tiler base class and threads it through detection and instance-segmentation tilers so callers can skip the expensive per-tile saliency-map merge when it’s not needed.
Changes:
- Add
merge_saliency_mapstoTilerand propagate it throughDetectionTilerandInstanceSegmentationTiler. - Gate saliency-map merging in
_merge_resultsfor detection and instance segmentation based onself.merge_saliency_maps. - Add/extend unit tests to validate the new flag’s default and configurability (including an instance-segmentation skip test).
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| model_api/src/model_api/tilers/tiler.py | Adds merge_saliency_maps to the base tiler and documents the performance motivation. |
| model_api/src/model_api/tilers/detection.py | Threads the flag into DetectionTiler and gates saliency merging in _merge_results. |
| model_api/src/model_api/tilers/instance_segmentation.py | Threads the flag into InstanceSegmentationTiler and skips saliency merging when disabled. |
| model_api/tests/unit/tilers/test_tiler.py | Adds base-tiler tests for the new attribute default, constructor behavior, and mutability. |
| model_api/tests/unit/tilers/test_detection_tiler.py | Extends init tests to cover the new flag. |
| model_api/tests/unit/tilers/test_instance_segmentation_tiler.py | Extends init tests and adds coverage ensuring saliency merge is skipped when disabled. |
Suppressed comments (3)
model_api/src/model_api/tilers/instance_segmentation.py:35
- This docstring says "semantic segmentation" but this class is for instance segmentation.
"""Constructor for creating a semantic segmentation tiling pipeline
model_api/src/model_api/tilers/detection.py:120
- There’s no unit test ensuring
_merge_saliency_mapsis skipped whenmerge_saliency_maps=Falsefor DetectionTiler (only init is tested). Since this change is specifically a performance optimization, a regression test would help prevent accidentally reintroducing the expensive merge call.
saliency_map = (
self._merge_saliency_maps(saliency_maps, shape, tiles_coords)
if saliency_maps and self.merge_saliency_maps
else np.ndarray(0)
)
model_api/src/model_api/tilers/tiler.py:51
configuration: dict = {}is a shared mutable default. PreferNone+ normalization to avoid accidental cross-instance state sharing (and to keep the constructor safe if config handling ever starts mutating the dict).
def __init__(
self,
model,
configuration: dict = {},
execution_mode: str = "async",
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DetectionTiler._merge_saliency_maps merges per-tile saliency maps with a pure-Python, pixel-by-pixel nested loop (cost O(num_tiles * num_classes * H * W)). With the default tiling configuration (tile_size=400, tiles_overlap=0.5), a single large image can be split into hundreds of tiles, making that merge take minutes to hours for callers that never use the merged saliency map (e.g. when only computing detection accuracy metrics rather than an explanation).
Add a merge_saliency_maps: bool = True constructor parameter/attribute to the base Tiler class (inherited by DetectionTiler and InstanceSegmentationTiler). When set to False, the expensive per-tile saliency merge is skipped entirely. It is a plain mutable attribute so callers can toggle it at any time, not just at construction. Defaults to True, preserving existing behavior.
Before submitting