fix: /pause_generation with --tokenizer-worker-num > 1 - #21237
Closed
lawrence-harmonic wants to merge 4 commits into
Closed
lawrence-harmonic wants to merge 4 commits into
lawrence-harmonic wants to merge 4 commits into
Conversation
lawrence-harmonic
requested review from
CatherineSue,
JustinTong0323,
Ying1123,
hnyls2002,
ispobock,
merrymercy,
slin1237 and
xiezhq-hermann
as code owners
March 23, 2026 23:11
Contributor
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
lawrence-harmonic
force-pushed
the
fix/pause_multi_tokenizer
branch
from
March 24, 2026 05:50
90ecf63 to
8c2c6cd
Compare
Contributor
Author
|
/tag-and-rerun-ci |
/pause_generation sets `is_pause` only on one worker. /continue_generation unsets `is_pause` on a potentially different worker. e.g. with 8 workers, with 7/8 probability we will leave 1/8 of workers paused, thus 1/8 of all requests will hang. With PD disaggregation, with 15/64 probability a request will get routed to one worker which is paused and one worker which is not paused, and these requests will wait forever for KV transfer. We fix this by setting the pause state in shared memory and polling it to update the local `is_pause` / `is_pause_cond`. Note that the consistency of `is_pause` will be reduced to eventual consistency in the multi-worker case. e.g. a pause immediately followed by a weight update may result in the weight update not seeing `is_pause` set immediately. Thus, we change the logic to continue checking for the pause flag while waiting for the writer lock. NOTE: We do not fix the following existing issues: * /continue_generation is not safe during a weight update which started while paused * weight update with multi-worker without pausing is not safe, i.e. `self.model_update_lock.writer_lock` is local, but the lock needs to be acquired across all workers
lawrence-harmonic
force-pushed
the
fix/pause_multi_tokenizer
branch
from
April 17, 2026 18:39
a3893a4 to
37a3c7d
Compare
Contributor
Author
|
/tag-and-rerun-ci |
Collaborator
|
Thanks for the contribution! We will merge this in #24462 and have added you as a co-author. |
5 tasks
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.
Motivation
Fix #21235
Modifications
We set the pause state in shared memory and poll it to update the local
is_pause/is_pause_cond. Note that the consistency ofis_pausewill be reduced to eventual consistency in the multi-worker case. e.g. a pause immediately followed by a weight update may result in the weight update not seeingis_pauseset immediately. Thus, we change the logic to continue checking for the pause flag while waiting for the writer lock.The introduction of
RWConditionis to achieve the following: we want to block others from changingis_pauseduring weight update, but not from pollingis_pause.NOTE: We do not fix the following existing issues:
self.model_update_lock.writer_lockis process-local, thus does not actually ensure global exclusivityIn my opinion, the most correct way to do synchronization would be to have a system-wide model rwlock. Then, take reader locks in the schedulers instead of the tokenizers (maybe also take the writer locks in the schedulers instead of the tokenizers). The schedulers can release lock when paused. Then update weights could then just always take the model lock, simplifying the pause vs lock casework (skipping the lock, as we do now, technically works now but is a bit strange).