Repository navigation
[None][feat] Support CancelRequest for Disaggregated Serving #6587
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 | ||||
|---|---|---|---|---|---|---|
|
|
@@ -379,6 +379,48 @@ class CacheSender::Impl | |||||
| mFormatter->format(*session); | ||||||
| } | ||||||
|
|
||||||
| bool cancelRequest(LlmRequest const& llmRequest) | ||||||
| { | ||||||
| bool isCancelled = false; | ||||||
| std::scoped_lock lkResp(mSenderMutex); | ||||||
| auto it = mReadyResponses.find(llmRequest.mRequestId); | ||||||
| // If the request is not the current request and already in the ready queue, we can cancel it. | ||||||
| if (it != mReadyResponses.end() && (!isSending() || getCurrentRequestId() != llmRequest.mRequestId)) | ||||||
| { | ||||||
| mCancelledRequests.insert(llmRequest.mRequestId); | ||||||
| isCancelled = true; | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| TLLM_LOG_WARNING("Cannot cancel request %zu", llmRequest.mRequestId); | ||||||
| } | ||||||
| return isCancelled; | ||||||
| } | ||||||
|
|
||||||
| void sendReadySignal(LlmRequest::RequestIdType requestId, bool isReady) | ||||||
| { | ||||||
| auto it = mRequestToSession.find(requestId); | ||||||
| TLLM_CHECK(it != mRequestToSession.end()); | ||||||
| auto& session = it->second; | ||||||
| auto const& connections = session.getConnections(); | ||||||
| for (size_t i = 0; i < connections.size(); i++) | ||||||
| { | ||||||
| auto* agentConnectionManager = dynamic_cast<executor::kv_cache::AgentConnectionManager*>(mManager); | ||||||
| if (agentConnectionManager != nullptr) | ||||||
|
Collaborator
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.
Suggested change
|
||||||
| { | ||||||
| auto* agentConnection = dynamic_cast<executor::kv_cache::AgentConnection const*>(connections.at(i)); | ||||||
| TLLM_CHECK(agentConnection); | ||||||
| agentConnection->sendReadySignal( | ||||||
| executor::kv_cache::DataContext{TransceiverTag::kREADY_SIGNAL_TAG}, isReady); | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| connections.at(i)->send( | ||||||
| executor::kv_cache::DataContext{TransceiverTag::kREADY_SIGNAL_TAG}, &isReady, sizeof(isReady)); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| ~Impl() | ||||||
| { | ||||||
| terminate(); | ||||||
|
|
@@ -463,8 +505,41 @@ class CacheSender::Impl | |||||
| { | ||||||
| mRemainSendCount.erase(reqId); | ||||||
|
|
||||||
| asyncSendAndRemoveResponse(it->first, std::move(it->second)); | ||||||
| removeResponse(it); | ||||||
| // Check if the request is cancelled | ||||||
| bool isReady = true; | ||||||
| { | ||||||
| std::scoped_lock lk(mSenderMutex); | ||||||
| if (mCancelledRequests.find(reqId) != mCancelledRequests.end()) | ||||||
| { | ||||||
| isReady = false; | ||||||
| } | ||||||
| } | ||||||
| sendReadySignal(reqId, isReady); | ||||||
|
|
||||||
| if (isReady) | ||||||
| { | ||||||
| asyncSendAndRemoveResponse(it->first, std::move(it->second)); | ||||||
| removeResponse(it); | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| // TODO: if the generation does not require the kv cache, the request will | ||||||
| // not be removed from mCancelledRequests. This should be handled by timeout. | ||||||
| auto it = mReadyResponses.find(mCurrentRequest.value()); | ||||||
|
Collaborator
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. Should we check that
Collaborator
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. I think that we do not need to check. The logic comes here because the request has been cancelled. In the |
||||||
| { | ||||||
| std::scoped_lock lkResp(mSenderMutex); | ||||||
| mReadyResponses.erase(it); | ||||||
| mCancelledRequests.erase(mCurrentRequest.value()); | ||||||
| mRemainSendCount.erase(mCurrentRequest.value()); | ||||||
| } | ||||||
| mCurrentRequest = std::nullopt; | ||||||
|
|
||||||
| if (mReadyResponses.empty()) | ||||||
| { | ||||||
| std::unique_lock lk(mCondMutex); | ||||||
| mAnyReady = false; | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
| mCurrentRequest = std::nullopt; | ||||||
| } | ||||||
|
|
@@ -491,7 +566,11 @@ class CacheSender::Impl | |||||
| auto const& requestInfo = recvRequestInfo(); | ||||||
| auto reqId = requestInfo.getRequestId(); | ||||||
|
|
||||||
| mCurrentRequest = reqId; | ||||||
| { | ||||||
| std::scoped_lock lk(mSenderMutex); | ||||||
| mCurrentRequest = reqId; | ||||||
| } | ||||||
|
|
||||||
| if (mRemainSendCount.find(reqId) == mRemainSendCount.end()) | ||||||
| { | ||||||
| mRemainSendCount[reqId] = getCounterpartsCount(reqId); | ||||||
|
|
@@ -572,6 +651,7 @@ class CacheSender::Impl | |||||
|
|
||||||
| private: | ||||||
| std::optional<RequestIdType> mCurrentRequest; | ||||||
| std::set<LlmRequest::RequestIdType> mCancelledRequests; | ||||||
| std::map<RequestIdType, Response> mReadyResponses; | ||||||
| std::mutex mSenderMutex, mCondMutex; | ||||||
| std::atomic<bool> mAnyReady{false}, mTerminate{false}; | ||||||
|
|
@@ -777,6 +857,62 @@ class CacheReceiver::Impl | |||||
| connection->send(DataContext{TransceiverTag::kINFO_TAG}, serializedInfo.data(), infoSize); | ||||||
| } | ||||||
|
|
||||||
| bool cancelRequest(LlmRequest const& llmRequest) | ||||||
| { | ||||||
|
|
||||||
| std::string processInfo = "default"; | ||||||
|
Collaborator
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. "default" should be stored in a static variable since it's used in a few places.
Suggested change
|
||||||
| if (common::getEnvRequestKVCacheConcurrent()) | ||||||
| { | ||||||
| processInfo = llmRequest.getDataTransceiverState().getCommState()->toString(); | ||||||
| } | ||||||
|
|
||||||
| bool isCancelled = false; | ||||||
| auto& asyncResource = mInstanceToAsyncResource.at(processInfo); | ||||||
| { | ||||||
| std::unique_lock<std::mutex> lck(asyncResource->mMtxForQueue); | ||||||
| auto it = std::find_if(asyncResource->mRequestsQueue.begin(), asyncResource->mRequestsQueue.end(), | ||||||
| [&llmRequest](RequestAndPromise const& requestAndPromise) | ||||||
| { return requestAndPromise.mRequest->mRequestId == llmRequest.mRequestId; }); | ||||||
| if (it != asyncResource->mRequestsQueue.end()) | ||||||
| { | ||||||
| asyncResource->mRequestsQueue.erase(it); | ||||||
| isCancelled = true; | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| TLLM_LOG_WARNING("Cannot cancel request %zu", llmRequest.mRequestId); | ||||||
| } | ||||||
| } | ||||||
| return isCancelled; | ||||||
| } | ||||||
|
|
||||||
| bool receiveReadySignal(TransferSession& session) | ||||||
| { | ||||||
| bool isReadyFinal = true; | ||||||
| bool isReady = false; | ||||||
| auto const& connections = session.getConnections(); | ||||||
|
|
||||||
| for (size_t i = 0; i < connections.size(); i++) | ||||||
| { | ||||||
| auto* agentConnectionManager = dynamic_cast<executor::kv_cache::AgentConnectionManager*>(mManager); | ||||||
| if (agentConnectionManager != nullptr) | ||||||
|
Collaborator
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.
Suggested change
|
||||||
| { | ||||||
| auto* agentConnection = dynamic_cast<executor::kv_cache::AgentConnection const*>(connections.at(i)); | ||||||
| TLLM_CHECK(agentConnection); | ||||||
| isReady = agentConnection->recvReadySignal( | ||||||
| executor::kv_cache::DataContext{TransceiverTag::kREADY_SIGNAL_TAG}); | ||||||
| } | ||||||
| else | ||||||
| { | ||||||
| connections.at(i)->recv( | ||||||
| executor::kv_cache::DataContext{TransceiverTag::kREADY_SIGNAL_TAG}, &isReady, sizeof(isReady)); | ||||||
| } | ||||||
| isReadyFinal &= isReady; | ||||||
| } | ||||||
|
|
||||||
| return isReadyFinal; | ||||||
| } | ||||||
|
|
||||||
| ~Impl() | ||||||
| { | ||||||
| for (auto&& [processInfo, asyncResource] : mInstanceToAsyncResource) | ||||||
|
|
@@ -799,6 +935,14 @@ class CacheReceiver::Impl | |||||
| llmRequest.setKvCacheTransferStart(std::chrono::steady_clock::now()); | ||||||
| TLLM_CUDA_CHECK(cudaSetDevice(mDeviceId)); | ||||||
| auto session = sendRequestInfo(llmRequest); | ||||||
| bool isReady = receiveReadySignal(session); | ||||||
| if (!isReady) | ||||||
| { | ||||||
| // Reuse the error state for the cancelled request. | ||||||
| llmRequest.setState(LlmRequestState::kDISAGG_TRANS_ERROR); | ||||||
| llmRequest.setKvCacheTransferEnd(std::chrono::steady_clock::now()); | ||||||
| return; | ||||||
| } | ||||||
| receiveSync(session); | ||||||
| llmRequest.setKvCacheTransferEnd(std::chrono::steady_clock::now()); | ||||||
|
|
||||||
|
|
@@ -970,6 +1114,16 @@ RequestInfo CacheSender::recvRequestInfo() | |||||
| return mImpl->recvRequestInfo(); | ||||||
| } | ||||||
|
|
||||||
| bool CacheSender::cancelRequest(LlmRequest const& llmRequest) | ||||||
| { | ||||||
| return mImpl->cancelRequest(llmRequest); | ||||||
| } | ||||||
|
|
||||||
| void CacheSender::sendReadySignal(LlmRequest::RequestIdType requestId, bool isReady) | ||||||
| { | ||||||
| mImpl->sendReadySignal(requestId, isReady); | ||||||
| } | ||||||
|
|
||||||
| CacheReceiver::CacheReceiver(executor::kv_cache::ConnectionManager* manager, | ||||||
| executor::kv_cache::CacheState selfCacheState, SizeType32 selfIndex, std::unique_ptr<BaseCacheFormatter> formatter) | ||||||
| : mImpl{std::unique_ptr<Impl, ImplDeleter>(new Impl(manager, selfCacheState, selfIndex, std::move(formatter)))} | ||||||
|
|
@@ -993,4 +1147,14 @@ void CacheReceiver::receiveSync(TransferSession& session) | |||||
| mImpl->receiveSync(session); | ||||||
| } | ||||||
|
|
||||||
| bool CacheReceiver::cancelRequest(LlmRequest const& llmRequest) | ||||||
| { | ||||||
| return mImpl->cancelRequest(llmRequest); | ||||||
| } | ||||||
|
|
||||||
| bool CacheReceiver::receiveReadySignal(TransferSession& session) | ||||||
| { | ||||||
| return mImpl->receiveReadySignal(session); | ||||||
| } | ||||||
|
|
||||||
| } // namespace tensorrt_llm::batch_manager | ||||||
Uh oh!
There was an error while loading. Please reload this page.