5353#include " tensorrt_llm/runtime/utils/mpiUtils.h"
5454#include " tensorrt_llm/runtime/utils/pgUtils.h"
5555#include < algorithm>
56+ #include < chrono>
5657#include < cstddef>
5758#include < numeric>
5859#include < unordered_map>
@@ -66,6 +67,20 @@ std::mutex CacheTransceiver::mDllMutex;
6667namespace
6768{
6869
70+ constexpr int kTransferFuturePollIntervalMs = 10 ;
71+
72+ // Finite status checks are scheduler polls, not terminal deadlines. Keep each
73+ // slice short so the caller can yield back to scheduling and transfer progress.
74+ std::chrono::milliseconds getTransferFuturePollInterval (std::optional<int > const & configuredTimeoutMs)
75+ {
76+ auto waitMs = kTransferFuturePollIntervalMs ;
77+ if (configuredTimeoutMs.has_value ())
78+ {
79+ waitMs = std::max (1 , std::min (configuredTimeoutMs.value (), kTransferFuturePollIntervalMs ));
80+ }
81+ return std::chrono::milliseconds (waitMs);
82+ }
83+
6984using RequestIdType = LlmRequest::RequestIdType;
7085
7186enum class TransferConsensusState : std::uint64_t
@@ -700,13 +715,13 @@ void updateKVCacheTransferBW(std::shared_ptr<CacheTransceiverComm> const& mComm,
700715RequestStatuses CacheTransceiver::checkContextTransferStatus (
701716 std::optional<int > const & atLeastRequestNum, bool markComplete)
702717{
703- bool blockAll = !atLeastRequestNum.has_value ();
718+ bool const blockAll = !atLeastRequestNum.has_value ();
704719 std::optional<int > senderFutureTimeoutMs = std::nullopt ;
705- // If blockAll is true, we want to block and not use a timeout
706- if (!blockAll && mCacheTransceiverConfig .has_value ())
720+ if (mCacheTransceiverConfig .has_value ())
707721 {
708722 senderFutureTimeoutMs = mCacheTransceiverConfig ->getKvTransferSenderFutureTimeoutMs ();
709723 }
724+ auto const futurePollInterval = getTransferFuturePollInterval (senderFutureTimeoutMs);
710725 // Observe-only: WARN per-request when the wall-clock transfer time exceeds
711726 // kvTransferTimeoutMs. No cancellation, eviction, or state transition.
712727 std::optional<int > kvTransferTimeoutMs = std::nullopt ;
@@ -770,27 +785,26 @@ RequestStatuses CacheTransceiver::checkContextTransferStatus(
770785 for (auto it = mSenderFutures .begin (); it != mSenderFutures .end ();)
771786 {
772787 auto & [request, future] = *it;
788+ auto const requestId = request->mRequestId ;
773789 if (kvTransferTimeoutMs.has_value ())
774790 {
775791 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
776792 LlmRequest::getSteadyClockNow () - request->getKvCacheTransferStart ());
777793 auto elapsedMs = static_cast <long >(elapsed.count ());
778- if (elapsedMs > kvTransferTimeoutMs.value () && mTimedOutSenderIds .insert (request-> mRequestId ).second )
794+ if (elapsedMs > kvTransferTimeoutMs.value () && mTimedOutSenderIds .insert (requestId ).second )
779795 {
780796 TLLM_LOG_WARNING (
781797 " Context KV cache transfer for request %ld exceeded configured timeout: "
782798 " elapsed %ld ms > limit %d ms (observe-only)." ,
783- request-> mRequestId , elapsedMs, kvTransferTimeoutMs.value ());
799+ requestId , elapsedMs, kvTransferTimeoutMs.value ());
784800 }
785801 }
786- if (blockAll || (toCompleteIdSet.find (request-> mRequestId ) != toCompleteIdSet.end ()))
802+ if (blockAll || (toCompleteIdSet.find (requestId ) != toCompleteIdSet.end ()))
787803 {
788- auto const requestId = request->mRequestId ;
789804 try
790805 {
791- // Wait for up to a specified timeout
792- auto status = future.wait_for (std::chrono::milliseconds (senderFutureTimeoutMs.value_or (0 )));
793- if (status == std::future_status::ready || !senderFutureTimeoutMs.has_value ())
806+ auto const status = blockAll ? std::future_status::ready : future.wait_for (futurePollInterval);
807+ if (status == std::future_status::ready)
794808 {
795809 future.get ();
796810 bool const failed = request->getState () == LlmRequestState::kDISAGG_TRANS_ERROR ;
@@ -800,8 +814,10 @@ RequestStatuses CacheTransceiver::checkContextTransferStatus(
800814 }
801815 else if (status == std::future_status::timeout)
802816 {
803- TLLM_LOG_WARNING (" Timed out waiting for context KV cache transfer after %d milliseconds." ,
804- senderFutureTimeoutMs.value ());
817+ TLLM_LOG_DEBUG (
818+ " Context KV cache transfer for request %ld is not ready after %ld ms wait slice; keeping it "
819+ " in progress." ,
820+ requestId, static_cast <long >(futurePollInterval.count ()));
805821 ++it;
806822 }
807823 else
@@ -866,7 +882,7 @@ RequestStatuses CacheTransceiver::checkContextTransferStatus(
866882
867883void CacheTransceiver::checkGenTransferStatus (std::optional<int > const & atLeastRequestNum)
868884{
869- bool blockAll = !atLeastRequestNum.has_value ();
885+ bool const blockAll = !atLeastRequestNum.has_value ();
870886 std::vector<LlmRequest::RequestIdType> genTransferReadyRequestIds;
871887 for (auto && [request, future] : mRequesterFutures )
872888 {
@@ -977,6 +993,13 @@ void CacheTransceiver::checkGenTransferStatus(std::optional<int> const& atLeastR
977993 " checkGenTransferStatus toCompleteIdSet size: %zu, atLeastRequestNum: %d " , toCompleteIdSet.size (),
978994 atLeastRequestNum.value_or (0 ));
979995 }
996+ std::optional<int > requesterFutureTimeoutMs = std::nullopt ;
997+ if (mCacheTransceiverConfig .has_value ())
998+ {
999+ requesterFutureTimeoutMs = mCacheTransceiverConfig ->getKvTransferSenderFutureTimeoutMs ();
1000+ }
1001+ auto const futurePollInterval = getTransferFuturePollInterval (requesterFutureTimeoutMs);
1002+
9801003 // Observe-only: gen-side mirror of the context-side timeout WARN.
9811004 std::optional<int > kvTransferTimeoutMs = std::nullopt ;
9821005 if (mCacheTransceiverConfig .has_value ())
@@ -992,28 +1015,48 @@ void CacheTransceiver::checkGenTransferStatus(std::optional<int> const& atLeastR
9921015 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
9931016 LlmRequest::getSteadyClockNow () - request->getKvCacheTransferStart ());
9941017 auto elapsedMs = static_cast <long >(elapsed.count ());
995- if (elapsedMs > kvTransferTimeoutMs.value () && mTimedOutRequesterIds .insert (request-> mRequestId ).second )
1018+ if (elapsedMs > kvTransferTimeoutMs.value () && mTimedOutRequesterIds .insert (requestId ).second )
9961019 {
9971020 TLLM_LOG_WARNING (
9981021 " Generation KV cache transfer for request %ld exceeded configured timeout: "
9991022 " elapsed %ld ms > limit %d ms (observe-only)." ,
1000- request-> mRequestId , elapsedMs, kvTransferTimeoutMs.value ());
1023+ requestId , elapsedMs, kvTransferTimeoutMs.value ());
10011024 }
10021025 }
10031026 if (blockAll || toCompleteIdSet.find (requestId) != toCompleteIdSet.end ())
10041027 {
10051028 try
10061029 {
1007- it->second .get ();
1008- bool const failed = request->getState () == LlmRequestState::kDISAGG_TRANS_ERROR ;
1009- if (failed)
1030+ auto const status = blockAll ? std::future_status::ready : it->second .wait_for (futurePollInterval);
1031+ if (status == std::future_status::ready)
10101032 {
1011- // The receiver uses the error state as a local transfer-failed signal.
1012- // Keep that signal local until the consensus outcome commits it globally.
1013- request->setState (LlmRequestState::kDISAGG_GENERATION_TRANS_IN_PROGRESS );
1033+ it->second .get ();
1034+ bool const failed = request->getState () == LlmRequestState::kDISAGG_TRANS_ERROR ;
1035+ if (failed)
1036+ {
1037+ // The receiver uses the error state as a local transfer-failed signal.
1038+ // Keep that signal local until the consensus outcome commits it globally.
1039+ request->setState (LlmRequestState::kDISAGG_GENERATION_TRANS_IN_PROGRESS );
1040+ }
1041+ recordLocalTransferOutcome (requestId, request, failed, mCompletedRequesterRequestIds ,
1042+ mFailedRequesterRequestIds , mRequesterRequestsAwaitingConsensus );
1043+ }
1044+ else if (status == std::future_status::timeout)
1045+ {
1046+ TLLM_LOG_DEBUG (
1047+ " Generation KV cache transfer for request %ld is not ready after %ld ms wait slice; keeping "
1048+ " it in progress." ,
1049+ requestId, static_cast <long >(futurePollInterval.count ()));
1050+ ++it;
1051+ continue ;
1052+ }
1053+ else
1054+ {
1055+ TLLM_LOG_ERROR (
1056+ " Future returned unexpected status for request %ld. Recording as failed." , requestId);
1057+ recordLocalTransferOutcome (requestId, request, /* failed=*/ true , mCompletedRequesterRequestIds ,
1058+ mFailedRequesterRequestIds , mRequesterRequestsAwaitingConsensus );
10141059 }
1015- recordLocalTransferOutcome (requestId, request, failed, mCompletedRequesterRequestIds ,
1016- mFailedRequesterRequestIds , mRequesterRequestsAwaitingConsensus );
10171060 }
10181061 catch (std::exception const & e)
10191062 {
0 commit comments