Repository navigation
feat: faster parallel S3 file downloads - #5102
Merged
Merged
Conversation
Replace pool.map with pool.imap_unordered(chunksize=1) to distribute download tasks one at a time across worker processes. pool.map batches tasks by chunksize, which can assign multiple large files to the same process for sequential processing. Benchmarked on g6e.4xlarge with Qwen3-4B (8GB) and Qwen3-VL-8B (16GB): - Qwen3-4B: 20s → 11.5s (1.7x faster) - Qwen3-VL-8B: 33s → 16s (2.1x faster) Signed-off-by: Jungwoo Song <bluayer@gmail.com>
bluayer
force-pushed
the
feat/fast-s3-uploader
branch
from
February 20, 2026 03:50
e3441da to
88c19a3
Compare
sivanantha321
approved these changes
Feb 20, 2026
Member
|
good find! |
sivanantha321
enabled auto-merge (squash)
February 20, 2026 08:58
spolti
added a commit
to spolti/kserve
that referenced
this pull request
Mar 3, 2026
Commits in this batch: a28ece4 feat: add annotation-based runtime defaults for MLServer (kserve#5064) af8ce37 feat: make agent container resources configurable (kserve#5127) aa153c3 ci: bump k8s & minikube version (kserve#5125) c2517a5 ci: add workflow to check if tests are passed before merge (kserve#5092) f5b211b fix(isvc): preserve reason/message on true conditions (kserve#5129) e3a6afb feat: add schedulerName field to ServingRuntimePodSpec (kserve#5073) 15748dc feat: allow storage init to download only selected files (kserve#5119) ce40a4b feat(llmisvc): add startupProbe to vLLM containers (kserve#5063) 972511a fix(llmisvc): preserve SchedulerConfigSpec conversion (kserve#5110) ee4d115 fix: add no-cache option for generate-versions-from-gomod.py (kserve#5123) 9283c48 fix: skip validation for empty modelcar fields (kserve#5083) 2f87143 feat: new env var INFERENCE_SERVICE_NAME (kserve#5013) 2f87143 fix(llmisvc): unblocks certificate renewal (kserve#5106) f650e31 fix: surface failure conditions in InferenceService status (kserve#5114) c596075 feat: include all required files to installation script (kserve#5103) f9a4a47 fix(llmisvc): return error from selectListener on mismatch (kserve#5105) 849c0e3 fix(llmisvc): restricts GlobalConfig fields for templates (kserve#5111) 1cc689a chore: Update OWNERS file (kserve#5112) 352a689 fix(llmisvc): handle JSON marshal error in ReplaceVariables (kserve#5109) d52e90c fix(llmisvc): return nil instead of empty InferencePoolSpec (kserve#5108) b7ae7d6 feat(llmisvc): add versioned well-known config resolution (kserve#5096) 900ca56 feat: inf. log batching, external marshalling support (kserve#5061) 15d1a26 feat(llmisvc): add DNS/IP SAN & renewal to self-signed certs (kserve#5099) b8fa0fb feat: faster parallel S3 file downloads (kserve#5102) fa290c6 feat: llmisvc supports scaling and HA for scheduler (kserve#5032)
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.
What this PR does / why we need it:
multiprocessing.Pool.mapdistributes tasks in batches (chunksize = ceil(N/(P*4))). When multiple large model shards end up in the same batch, they are downloaded sequentially by a single worker process while other processes sit idle.For example, Qwen3-4B has 27 files with 4 worker processes.
pool.mapcalculates chunksize = ceil(27/16) = 2, meaning tasks are dispatched in pairs. The files are listed in alphabetical order from S3:With chunksize=2, task[20] and task[21] can batched together and assigned to the same worker process. That single process downloads them sequentially (12s + 12s = 24s) while other processes finish their small files in under 1s and sit idle.
With
imap_unordered(chunksize=1), each task is dispatched individually to the next available worker. The two large shards are picked up by different processes and downloaded in parallel (~12s total).This pattern is common across LLM model repositories where large safetensor shards dominate the total download time alongside many small metadata/config files.
Which issue(s) this PR fixes:
Fixes #
Feature/Issue validation/testing:
Existing unit tests pass (37 passed)
E2E test on g6e.4xlarge with Qwen3-4B (~8GB, 3 shards): 20s → 11.5s
E2E test on g6e.4xlarge with Qwen3-VL-8B-Instruct (~16GB, 4 shards): 33s → 16s
Per-process analysis confirmed large shards are now assigned to different worker PIDs
Logs (pool.map)
Special notes for your reviewer:
imap_unorderedreturns an iterator instead of a list, so it is wrapped withlist()to maintain the same behavior aspool.map(wait for all tasks to complete before processing results).imap_unorderedmethod.Checklist: