Distributed multi-GPU dense feature extraction over slide ROIs#223
Merged
Conversation
Make dense (d, gh, gw) grid extraction a first-class distributed artifact, mirroring the pooled path: a dense run splits its caller-supplied ROIs across all visible GPUs and each rank writes its final grids directly (nobody gathers). Three-layer seam: - plan_dense_shards: pure, contiguous ROI-granularity np.array_split (balanced to +/-1, deterministic, exact partition). - run_dense_shard: device-agnostic encode+write loop reusing iter_regions_dense; writes one <x>_<y>.pt payload + <x>_<y>.meta.json sidecar per ROI, atomically and sidecar-last, skipping ROIs whose sidecar already exists (resume/crash-safe). - dense_worker: thin torchrun entry (env RANK/WORLD_SIZE, no NCCL; coords travel as an npz), plus dense_stage parent orchestration (flatten -> resume-filter -> resolve read plan -> in-process for num_gpus=1 or torchrun fan-out -> collect). Public API: Model.embed_regions_dense(regions, *, dense: DenseOptions, execution: ExecutionOptions) -> list[DenseRegionArtifact]. Python-only. New artifact: dense_embeddings/[<class>/]<sample_id>/<x>_<y>.pt (+ sidecar).
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.
Summary
Adds first-class distributed extraction for dense
(d, gh, gw)feature grids over caller-supplied WSI regions. ROIs are split across visible GPUs; each rank writes its final grids directly, avoiding a parent gather for artifacts that are roughly 1000× larger than pooled embeddings.This is the slide2vec prerequisite for soma #279. Scope is Python-only: no CLI, YAML, or manifest changes.
Architecture
SlideRegions, filters completed ROIs before sharding, resolves each slide's spacing-aware read plan once, and dispatches in-process fornum_gpus=1or through torchrun for multiple GPUs.plan_dense_shardsperforms deterministic, contiguous ROI-levelnp.array_split, balanced to ±1 ROI. No batch alignment is needed because features depend on batch size, not batch composition (ADR 0002).run_dense_shardgroups consecutive ROIs by slide, reusesiter_regions_densefor batched reads and encoding, and persists one payload plus sidecar per ROI.dense_workerreadsRANK,WORLD_SIZE, andLOCAL_RANKfrom torchrun, loads coordinates from NPZ, and runs its shard without NCCL or process-group initialization.Ranks persist dense artifacts directly; nobody gathers grids in the parent (ADR 0001).
Public interface and artifacts
Artifact layout:
Sidecars contain extraction geometry and encoding parameters owned by slide2vec; downstream supervision metadata remains downstream.
Reliability and safety
cwd.output_direven through existing symlinks.num_workers_per_gpu.Verification
test_plan_dense_shards_*test_run_dense_shard_writes_payload_and_sidecar_per_regiontest_multi_rank_matches_single_ranktest_run_dense_shard_skips_regions_with_existing_sidecar,test_run_dense_shard_reencodes_payload_missing_its_sidecar,test_write_dense_region_does_not_publish_interrupted_sidecartest_embed_regions_dense_num_gpus_one_runs_in_processtest_embed_regions_dense_num_gpus_gt_one_launches_dense_worker,test_dense_worker_encodes_only_its_rank_shard,test_region_specs_round_trip_through_requesttest_region_dense_paths_rejects_*,test_package_root_exports_apiTest result
python -m pytest --no-cov -q -m "not heavy": 496 passed, 1 skipped, 25 deselected.Final structured review: clean, no actionable findings.
Near-linear speedup remains a manual multi-GPU acceptance check because CI has no GPU.
Closes #217