diff --git a/python/sglang/srt/managers/cache_controller.py b/python/sglang/srt/managers/cache_controller.py index 46e32f878..1d04405f0 100644 --- a/python/sglang/srt/managers/cache_controller.py +++ b/python/sglang/srt/managers/cache_controller.py @@ -427,6 +427,19 @@ class HiCacheController: self.pp_size = pp_size self.enable_storage_metrics = enable_storage_metrics + # Resolve this rank's parallel identity once, unconditionally -- not only + # when a storage backend is configured. CP shared-L2 attaches no storage + # backend, yet per-rank consumers (e.g. the CP HiCache metrics collector) + # still need tp_rank/tp_size/dp_rank. + if is_dp_attention_enabled(): + self.tp_rank = get_attention_tp_rank() + self.tp_size = get_attention_tp_size() + self.dp_rank = get_attention_dp_rank() + else: + self.tp_rank = get_tensor_model_parallel_rank() + self.tp_size = get_tensor_model_parallel_world_size() + self.dp_rank = 0 + # Default storage page IO functions (may be overridden by attach). self.page_get_func = self._generic_page_get self.page_set_func = self._generic_page_set @@ -788,15 +801,8 @@ class HiCacheController: if storage_backend_extra_config is None: storage_backend_extra_config = {} - if is_dp_attention_enabled(): - self.tp_rank = get_attention_tp_rank() - self.tp_size = get_attention_tp_size() - self.dp_rank = get_attention_dp_rank() - else: - self.tp_rank = get_tensor_model_parallel_rank() - self.tp_size = get_tensor_model_parallel_world_size() - self.dp_rank = 0 - + # tp_rank/tp_size/dp_rank are resolved once in __init__ (always available, + # including under CP shared-L2 where no storage backend is attached). # Currently, NPUMLATokenToKVPool is the subclass of MLATokenToKVPool. is_mla_backend = isinstance(self.mem_pool_device, MLATokenToKVPool) # Least Common Multiple among heterogeneous tp size diff --git a/python/sglang/srt/mem_cache/hiradix_cache.py b/python/sglang/srt/mem_cache/hiradix_cache.py index bf02baa8a..93b9ee5a1 100644 --- a/python/sglang/srt/mem_cache/hiradix_cache.py +++ b/python/sglang/srt/mem_cache/hiradix_cache.py @@ -3910,7 +3910,13 @@ class HiRadixCache(RadixCache): from sglang.srt.observability.metrics_collector import CpHiCacheMetricsCollector cc = self.cache_controller + # cp_rank/cp_size are the identity that actually distinguishes the + # per-rank L2 lanes / L3 slabs (what these metrics measure); tp/dp/pp + # give the full parallel coordinate. cp_* come from the CP layout + # (_cp_hicache_cp_*), the rest from the controller (always set). labels = { + "cp_rank": self._cp_hicache_cp_rank(), + "cp_size": self._cp_hicache_cp_size(), "tp_rank": cc.tp_rank, "dp_rank": cc.dp_rank, "pp_rank": cc.pp_rank, "pp_size": cc.pp_size, } diff --git a/python/sglang/srt/observability/metrics_collector.py b/python/sglang/srt/observability/metrics_collector.py index 47da6db75..461378e11 100644 --- a/python/sglang/srt/observability/metrics_collector.py +++ b/python/sglang/srt/observability/metrics_collector.py @@ -1464,7 +1464,8 @@ class CpHiCacheMetricsCollector: Gauges for instantaneous state (occupancy, inflight, queue depths); Counters for cumulative work (spill/reload pages, GC reclaims, write errors, L2 commit/evict). Fed periodically off the allocator's - occupancy_by_payload()/stats() + CpL3Store.stats(). Per-rank via the tp_rank label. The mainline + occupancy_by_payload()/stats() + CpL3Store.stats(). Per-rank via the cp_rank label (each CP rank owns + its own L2 lane + L3 slabs); tp/dp/pp labels give the full parallel coordinate. The mainline StorageMetricsCollector is dead under CP (enable_storage=False), so this is the only L2/L3 visibility. """