Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
06845db
Add KV cache v2 SWA scratch reuse
jiaganc May 26, 2026
55e3154
[None][fix] disagg-ctx: detach kv_cache page-index buffers on early I…
jiaganc Jun 25, 2026
6ad5120
[None][chore] memory observability probes for DSv4 mem-opts validatio…
jiaganc Jun 25, 2026
6b6eb9d
[TRTLLM-13017][fix] disagg gen init: use prompt_len for SWA history_l…
jiaganc Jun 25, 2026
00f6bd6
[None][feat] kv_cache_manager_v2: surface host-tier 'dropped before r…
jiaganc Jun 25, 2026
8896601
[None][feat] Insert sync to wait prepare_inputs before update_request…
jiaganc Jun 25, 2026
2d92836
[None][feat] Add per-iteration cached KV length to iter log (#14734)
jiaganc Jun 25, 2026
8bb97f6
[None][perf] PyExecutor: skip empty MPI collectives in _fetch_new_req…
jiaganc Jun 25, 2026
193392f
[None][fix] Remove context KV cache allocation rollback (#14849)
jiaganc Jun 25, 2026
cde681f
[None][feat] improve iteration stats reporting (#14897)
jiaganc Jun 25, 2026
fc5c0ad
[None][perf] disagg: serialize Request input_token_ids as int32 bytes…
jiaganc Jun 25, 2026
4bf4703
[None][perf] executor: memcpy int32 token buffer into tle::Request ct…
jiaganc Jun 25, 2026
b7e5df3
[None][feat] Add V2 SWA scratch reuse config switch
jiaganc Jun 26, 2026
1a7df3a
[None][fix] restore lazy iteration stats buffer creation
jiaganc Jun 26, 2026
2d2cfda
[None][fix] Enable V2 KV cache stats from perf metrics
jiaganc Jun 26, 2026
96045a5
[None][fix] Restore V2 context resource updates
jiaganc Jun 26, 2026
02b4e4f
[None][fix] Add Request num_input_tokens accessor
jiaganc Jun 26, 2026
8729444
[None][fix] Restore executor input copy wait hook
jiaganc Jun 26, 2026
76e17a6
[None][fix] Drop extra input copy wait
jiaganc Jun 26, 2026
de1cd8d
[TRTLLM-12229][perf] Optimize DSV4 block table copy paths (#14338)
jiaganc Jun 29, 2026
7a3cfa5
[TRTLLM-12229][fix] Fix MTP by scratch reuse rewind (#14403)
jiaganc Jun 29, 2026
35b0f36
[None][feat] add DSV4 KV cache pool ratio config (#14623)
jiaganc Jun 29, 2026
72c99b4
[TRTLLM-13017][fix] consolidate disagg gen init KV setup into prepare…
jiaganc Jun 29, 2026
b739cc2
[TRTLLM-12229][perf] Cache scratch memory optimization for DSv4 (#14564)
jiaganc Jun 29, 2026
cabfe34
[None][fix] Fix kv cache manager v2 size estimation (#14698)
jiaganc Jun 29, 2026
9135dc7
[None][fix] Fix KV cache size estimation limits (#15091)
jiaganc Jun 29, 2026
6d5e751
[None][feat] Add KV cache block reuse policy (#15046)
jiaganc Jun 29, 2026
e40f597
[None][fix] Fix V2 context finalization ordering (#15307)
jiaganc Jun 29, 2026
9d24c98
[None][perf] Use debug NVTX ranges in DSv4 cache manager
jiaganc Jun 29, 2026
766cc99
[None][refactor] Inline KV cache pool mapping setup
jiaganc Jun 29, 2026
25917f5
[None][test] Remove DSv4 Flash disaggregated accuracy tests
jiaganc Jun 29, 2026
18f7e57
[None][test] Remove chat prompt token regression tests
jiaganc Jun 29, 2026
10c1855
[None][revert] Revert OpenAI iteration stats changes
jiaganc Jun 29, 2026
67f6023
[None][doc] Document iteration stats buffer assumption
jiaganc Jun 29, 2026
1007542
[None][fix] Bound batched executor stats retention
jiaganc Jun 29, 2026
e7db96e
[None][fix] Validate serialized request token buffer
jiaganc Jun 29, 2026
935513c
[None][fix] Refresh cached KV stats for incremental updates
jiaganc Jun 29, 2026
6f55ca1
[None][test] Cover VisualGen iteration stats endpoint
jiaganc Jun 29, 2026
ba04cd4
[None][fix] Address disaggregated transfer review findings
jiaganc Jun 29, 2026
8dc25a3
Merge branch 'main' into main-dsv4-cache-manager-mergeback-round2
jiaganc Jun 30, 2026
9d97f77
[None][chore] Document prompt token buffer sync invariant
jiaganc Jun 30, 2026
52a2e5f
[None][test] Fix KV cache budget split fixture
jiaganc Jun 30, 2026
58ebb31
[None][fix] Guard input-copy wait for non-PyTorch engines
jiaganc Jul 1, 2026
60313fe
[None][fix] Restore V2 context rollback paths
jiaganc Jul 1, 2026
a2af07e
[None][fix] Handle unbounded iter stats buffer
jiaganc Jul 1, 2026
56168b5
[None][fix] Remove dead DSV4 staging tensors
jiaganc Jul 1, 2026
ccdf441
Merge branch 'main' into main-dsv4-cache-manager-mergeback-round2
jiaganc Jul 2, 2026
593c28b
Merge remote-tracking branch 'upstream/main' into main-dsv4-cache-man…
jiaganc Jul 2, 2026
3956a85
[None][fix] Fix V2 cache setup in transceiver harness
jiaganc Jul 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions cpp/include/tensorrt_llm/batch_manager/kvCacheManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,19 +327,32 @@ struct KvCacheStats
std::size_t allocatedBytes{};
};

/// @brief Per-iteration KV cache statistics. All delta counters represent changes since the last call to
/// getIterationStats(). Gauges are instantaneous snapshots.
/// @brief Per-iteration KV cache statistics. All delta counters and peak gauges represent values since the last call
/// to getIterationStats(). Snapshot gauges are instantaneous.
struct KvCacheIterationStats
{
// --- Instantaneous gauges ---
// Primary (GPU) pool
SizeType32 primaryMaxNumBlocks{0};
SizeType32 primaryFreeNumBlocks{0};
SizeType32 primaryUsedNumBlocks{0};
// Cached-but-unpinned blocks in the primary pool. Distinct from primaryUsedNumBlocks,
// which also counts blocks pinned during onboard memcpy windows.
SizeType32 primaryEvictableNumBlocks{0};
SizeType32 primaryPeakFreeNumBlocks{0};
SizeType32 primaryPeakUsedNumBlocks{0};
SizeType32 primaryPeakEvictableNumBlocks{0};
// Secondary (host) pool
SizeType32 secondaryMaxNumBlocks{0};
SizeType32 secondaryFreeNumBlocks{0};
SizeType32 secondaryUsedNumBlocks{0};
// Cached-but-unpinned blocks in the secondary pool. Useful to gauge "how full is the
// host cache"; secondaryUsedNumBlocks only counts pinned blocks during the sub-ms
// onboard memcpy window so it cannot answer that question on its own.
SizeType32 secondaryEvictableNumBlocks{0};
SizeType32 secondaryPeakFreeNumBlocks{0};
SizeType32 secondaryPeakUsedNumBlocks{0};
SizeType32 secondaryPeakEvictableNumBlocks{0};

// --- Per-iteration deltas (reset on each read) ---
// Context phase: block allocation and reuse
Expand All @@ -361,6 +374,11 @@ struct KvCacheIterationStats
// Intra-device (GPU → GPU) block copies (e.g. partial reuse when source block has refs)
SizeType32 iterIntraDeviceCopyBlocks{0};
std::size_t iterIntraDeviceCopyBytes{0};

// Pages released by LRU from the last cache tier without ever being onboarded back
// to GPU during their stay at that tier (i.e. fully dropped from the hierarchy).
SizeType32 iterHostDroppedBlocks{0};
std::size_t iterHostDroppedBytes{0};
};

// Basic building block of a paged KV cache - a single
Expand Down
9 changes: 7 additions & 2 deletions cpp/include/tensorrt_llm/executor/executor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1556,6 +1556,9 @@ class ExecutorConfig
// Per request stats may have additional overhead due to going through all requests. Turned off by default.
static constexpr SizeType32 kDefaultRequestStatsMaxIterations = 0;

// A value of -1 keeps all iteration/request stats until they are fetched.
static constexpr SizeType32 kUnlimitedStatsMaxIterations = -1;

explicit ExecutorConfig(SizeType32 maxBeamWidth = 1, SchedulerConfig schedulerConfig = SchedulerConfig(),
KvCacheConfig kvCacheConfig = KvCacheConfig(), bool enableChunkedContext = true, bool normalizeLogProbs = false,
SizeType32 iterStatsMaxIterations = kDefaultIterStatsMaxIterations,
Expand Down Expand Up @@ -1661,9 +1664,11 @@ class ExecutorConfig
bool mNormalizeLogProbs;

/// @brief Controls the maximum number of iterations for which to keep statistics.
/// Set to -1 to keep all iteration statistics. Set to 0 to disable iteration statistics.
SizeType32 mIterStatsMaxIterations;

/// @brief Controls the maximum number of iterations for which to keep per-request statistics.
/// Set to -1 to keep all per-request statistics. Set to 0 to disable per-request statistics.
SizeType32 mRequestStatsMaxIterations;

/// @brief The type of batching strategy to use. See BatchingType.
Expand Down Expand Up @@ -1944,12 +1949,12 @@ class Executor
void shutdown();

/// @brief Returns the per-iterations statistics computed since last call to getLatestIterationStats.
/// Contains at most iterStatsMaxIterations iterations.
/// Contains at most iterStatsMaxIterations iterations, or all iterations when set to -1.
/// @return Iteration stats
std::deque<IterationStats> getLatestIterationStats();

/// @brief Returns the request stats of each iteration computed since last call to getLatestRequestStats.
/// Contains at most requestStatsMaxIterations iterations.
/// Contains at most requestStatsMaxIterations iterations, or all iterations when set to -1.
/// @return Request stats grouped by iterations
std::deque<RequestStatsPerIteration> getLatestRequestStats();

Expand Down
2 changes: 1 addition & 1 deletion cpp/tensorrt_llm/executor/cacheTransceiverConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ CacheTransceiverConfig::CacheTransceiverConfig(std::optional<BackendType> backen
, mMaxTokensInBuffer(maxNumTokens)
, mKvTransferTimeoutMs(kvTransferTimeoutMs)
, mKvTransferSenderFutureTimeoutMs(kvTransferSenderFutureTimeoutMs)
, mKvTransferPollIntervalMs(kvTransferPollIntervalMs)
{
setKvTransferPollIntervalMs(kvTransferPollIntervalMs);
}

bool CacheTransceiverConfig::operator==(CacheTransceiverConfig const& other) const
Expand Down
10 changes: 5 additions & 5 deletions cpp/tensorrt_llm/executor/executorConfig.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -65,8 +65,8 @@ ExecutorConfig::ExecutorConfig(SizeType32 maxBeamWidth, SchedulerConfig schedule
, mEnableTrtOverlap(enableTrtOverlap)
, mFailFastOnAttentionWindowTooLarge(failFastOnAttentionWindowTooLarge)
{
TLLM_CHECK(iterStatsMaxIterations >= 0);
TLLM_CHECK(requestStatsMaxIterations >= 0);
TLLM_CHECK(iterStatsMaxIterations >= kUnlimitedStatsMaxIterations);
TLLM_CHECK(requestStatsMaxIterations >= kUnlimitedStatsMaxIterations);
TLLM_CHECK(mMaxBeamWidth > 0);
TLLM_CHECK(maxSeqIdleMicroseconds > 0);
}
Expand Down Expand Up @@ -271,13 +271,13 @@ void ExecutorConfig::setNormalizeLogProbs(bool normalizeLogProbs)
void ExecutorConfig::setIterStatsMaxIterations(SizeType32 iterStatsMaxIterations)
{
mIterStatsMaxIterations = iterStatsMaxIterations;
TLLM_CHECK(mIterStatsMaxIterations >= 0);
TLLM_CHECK(mIterStatsMaxIterations >= kUnlimitedStatsMaxIterations);
}

void ExecutorConfig::setRequestStatsMaxIterations(SizeType32 requestStatsMaxIterations)
{
mRequestStatsMaxIterations = requestStatsMaxIterations;
TLLM_CHECK(mRequestStatsMaxIterations >= 0);
TLLM_CHECK(mRequestStatsMaxIterations >= kUnlimitedStatsMaxIterations);
}

void ExecutorConfig::setBatchingType(BatchingType batchingType)
Expand Down
52 changes: 35 additions & 17 deletions cpp/tensorrt_llm/executor/executorImpl.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -86,6 +86,16 @@ namespace
return fixedExecutorConfig;
}

[[nodiscard]] bool statsBufferIsEnabled(SizeType32 maxIterations)
{
return maxIterations != 0;
}

[[nodiscard]] bool statsBufferIsBounded(SizeType32 maxIterations)
{
return maxIterations > 0;
}

SizeType32 getNumChildRequests(Request const& request)
{
auto samplingConfig = request.getSamplingConfig();
Expand Down Expand Up @@ -1908,34 +1918,38 @@ RequestStatsPerIteration Executor::Impl::getCurrentRequestStats(
void Executor::Impl::appendCurrentIterStats(IterationStats&& currentIterStats)
{
std::scoped_lock<std::mutex> lck(mIterStatsMtx);
if (mIterationStats.size() >= mIterStatsMaxIterations)
if (statsBufferIsBounded(mIterStatsMaxIterations))
{
mIterationStats.pop_front();
auto const maxIterStats = static_cast<std::size_t>(mIterStatsMaxIterations);
if (mIterationStats.size() >= maxIterStats)
{
mIterationStats.pop_front();
}
}
mIterationStats.emplace_back(std::move(currentIterStats));
}

void Executor::Impl::appendMultipleIterStats(std::vector<IterationStats>&& currentIterStatsVec)
{
std::scoped_lock<std::mutex> lck(mIterStatsMtx);
if (mIterationStats.size() + currentIterStatsVec.size() > mIterStatsMaxIterations)
mIterationStats.insert(mIterationStats.end(), std::make_move_iterator(currentIterStatsVec.begin()),
std::make_move_iterator(currentIterStatsVec.end()));
if (statsBufferIsBounded(mIterStatsMaxIterations))
{
size_t removeCount = mIterationStats.size() + currentIterStatsVec.size() - mIterStatsMaxIterations;
for (size_t i = 0; i < removeCount; i++)
auto const maxIterStats = static_cast<std::size_t>(mIterStatsMaxIterations);
while (mIterationStats.size() > maxIterStats)
{
mIterationStats.pop_front();
}
Comment thread
jiaganc marked this conversation as resolved.
}
mIterationStats.insert(mIterationStats.end(), std::make_move_iterator(currentIterStatsVec.begin()),
std::make_move_iterator(currentIterStatsVec.end()));
}

void Executor::Impl::updateIterationStats(RequestList const& activeRequests, double iterLatencyMS,
SizeType32 numNewActiveRequests, double newActiveRequestsQueueLatencyMS, SizeType32 numCompletedRequests,
bool flushToOrchestrator)
{
NVTX3_SCOPED_RANGE(updateIterationStats);
if (mIterStatsMaxIterations > 0 && mIsLeader)
if (statsBufferIsEnabled(mIterStatsMaxIterations) && mIsLeader)
{
auto currentIterStats = getCurrentIterationStats(
activeRequests, iterLatencyMS, numNewActiveRequests, newActiveRequestsQueueLatencyMS, numCompletedRequests);
Expand Down Expand Up @@ -1972,33 +1986,37 @@ void Executor::Impl::updateIterationStats(RequestList const& activeRequests, dou
void Executor::Impl::appendCurrentRequestStats(RequestStatsPerIteration&& currentRequestStats)
{
std::scoped_lock<std::mutex> lck(mRequestStatsMtx);
if (mRequestStats.size() >= mRequestStatsMaxIterations)
if (statsBufferIsBounded(mRequestStatsMaxIterations))
{
mRequestStats.pop_front();
auto const maxRequestStats = static_cast<std::size_t>(mRequestStatsMaxIterations);
if (mRequestStats.size() >= maxRequestStats)
{
mRequestStats.pop_front();
}
}
mRequestStats.emplace_back(std::move(currentRequestStats));
}

void Executor::Impl::appendMultipleRequestStats(std::vector<RequestStatsPerIteration>&& currentRequestStatsVec)
{
std::scoped_lock<std::mutex> lck(mRequestStatsMtx);
if (mRequestStats.size() + currentRequestStatsVec.size() > mRequestStatsMaxIterations)
mRequestStats.insert(mRequestStats.end(), std::make_move_iterator(currentRequestStatsVec.begin()),
std::make_move_iterator(currentRequestStatsVec.end()));
if (statsBufferIsBounded(mRequestStatsMaxIterations))
{
size_t removeCount = mRequestStats.size() + currentRequestStatsVec.size() - mRequestStatsMaxIterations;
for (size_t i = 0; i < removeCount; i++)
auto const maxRequestStats = static_cast<std::size_t>(mRequestStatsMaxIterations);
while (mRequestStats.size() > maxRequestStats)
{
mRequestStats.pop_front();
}
}
mRequestStats.insert(mRequestStats.end(), std::make_move_iterator(currentRequestStatsVec.begin()),
std::make_move_iterator(currentRequestStatsVec.end()));
}

void Executor::Impl::updateRequestStats(
RequestList const& activeRequests, RequestList const& finishedRequests, bool flushToOrchestrator)
{
NVTX3_SCOPED_RANGE(updateRequestStats);
if (mRequestStatsMaxIterations > 0 && mIsLeader)
if (statsBufferIsEnabled(mRequestStatsMaxIterations) && mIsLeader)
{
// Add current iteration request stats
auto currentRequestStats = getCurrentRequestStats(activeRequests, finishedRequests);
Expand Down
6 changes: 3 additions & 3 deletions cpp/tensorrt_llm/executor/executorImpl.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -310,12 +310,12 @@ class Executor::Impl
std::unordered_map<IdType, std::vector<IdType>> mChildReqIdsMap;

// Iteration stats
IterationType mIterStatsMaxIterations;
SizeType32 mIterStatsMaxIterations;
std::mutex mIterStatsMtx;
std::deque<IterationStats> mIterationStats;

// Request stats
IterationType mRequestStatsMaxIterations;
SizeType32 mRequestStatsMaxIterations;
std::mutex mRequestStatsMtx;
std::deque<RequestStatsPerIteration> mRequestStats;

Expand Down
12 changes: 11 additions & 1 deletion cpp/tensorrt_llm/nanobind/batch_manager/kvCacheManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,9 +379,17 @@ void tb::kv_cache_manager::KVCacheManagerBindings::initBindings(nb::module_& m)
.def_rw("primary_max_num_blocks", &tbk::KvCacheIterationStats::primaryMaxNumBlocks)
.def_rw("primary_free_num_blocks", &tbk::KvCacheIterationStats::primaryFreeNumBlocks)
.def_rw("primary_used_num_blocks", &tbk::KvCacheIterationStats::primaryUsedNumBlocks)
.def_rw("primary_evictable_num_blocks", &tbk::KvCacheIterationStats::primaryEvictableNumBlocks)
.def_rw("primary_peak_free_num_blocks", &tbk::KvCacheIterationStats::primaryPeakFreeNumBlocks)
.def_rw("primary_peak_used_num_blocks", &tbk::KvCacheIterationStats::primaryPeakUsedNumBlocks)
.def_rw("primary_peak_evictable_num_blocks", &tbk::KvCacheIterationStats::primaryPeakEvictableNumBlocks)
.def_rw("secondary_max_num_blocks", &tbk::KvCacheIterationStats::secondaryMaxNumBlocks)
.def_rw("secondary_free_num_blocks", &tbk::KvCacheIterationStats::secondaryFreeNumBlocks)
.def_rw("secondary_used_num_blocks", &tbk::KvCacheIterationStats::secondaryUsedNumBlocks)
.def_rw("secondary_evictable_num_blocks", &tbk::KvCacheIterationStats::secondaryEvictableNumBlocks)
.def_rw("secondary_peak_free_num_blocks", &tbk::KvCacheIterationStats::secondaryPeakFreeNumBlocks)
.def_rw("secondary_peak_used_num_blocks", &tbk::KvCacheIterationStats::secondaryPeakUsedNumBlocks)
.def_rw("secondary_peak_evictable_num_blocks", &tbk::KvCacheIterationStats::secondaryPeakEvictableNumBlocks)
.def_rw("iter_alloc_total_blocks", &tbk::KvCacheIterationStats::iterAllocTotalBlocks)
.def_rw("iter_alloc_new_blocks", &tbk::KvCacheIterationStats::iterAllocNewBlocks)
.def_rw("iter_reused_blocks", &tbk::KvCacheIterationStats::iterReusedBlocks)
Expand All @@ -395,7 +403,9 @@ void tb::kv_cache_manager::KVCacheManagerBindings::initBindings(nb::module_& m)
.def_rw("iter_offload_blocks", &tbk::KvCacheIterationStats::iterOffloadBlocks)
.def_rw("iter_offload_bytes", &tbk::KvCacheIterationStats::iterOffloadBytes)
.def_rw("iter_intra_device_copy_blocks", &tbk::KvCacheIterationStats::iterIntraDeviceCopyBlocks)
.def_rw("iter_intra_device_copy_bytes", &tbk::KvCacheIterationStats::iterIntraDeviceCopyBytes);
.def_rw("iter_intra_device_copy_bytes", &tbk::KvCacheIterationStats::iterIntraDeviceCopyBytes)
.def_rw("iter_host_dropped_blocks", &tbk::KvCacheIterationStats::iterHostDroppedBlocks)
.def_rw("iter_host_dropped_bytes", &tbk::KvCacheIterationStats::iterHostDroppedBytes);

nb::class_<tbk::BlockKey>(m, "BlockKey")
.def(nb::init<>())
Expand Down
Loading
Loading