A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 14, 05:30 UTC
[Log] Optimize Startup Log (#26740)
Signed-off-by: yewentao256 <zhyanwentao@126.com>
Wentao Ye committed
Oct 24, 2025 at 19:27 UTC
52efc34ebf289810909a2557ab181d868c560550
21 files changed
+151
-63
vllm/compilation/backends.py
+25
-10
@@ -245,10 +245,14 @@ class CompilerManager:
245
if graph_index == 0:
246
# adds some info logging for the first graph
247
if runtime_shape is None:
248
- logger.info("Cache the graph for dynamic shape for later use")
248
+ logger.info_once(
249
+ "Cache the graph for dynamic shape for later use", scope="local"
250
+ )
251
else:
250
- logger.info(
251
- "Cache the graph of shape %s for later use", str(runtime_shape)
252
+ logger.info_once(
253
+ "Cache the graph of shape %s for later use",
254
+ str(runtime_shape),
255
+ scope="local",
256
)
257
if runtime_shape is None:
258
logger.debug(
@@ -272,12 +276,17 @@ class CompilerManager:
276
elapsed = now - compilation_start_time
277
compilation_config.compilation_time += elapsed
278
if runtime_shape is None:
275
- logger.info("Compiling a graph for dynamic shape takes %.2f s", elapsed)
279
+ logger.info_once(
280
+ "Compiling a graph for dynamic shape takes %.2f s",
281
+ elapsed,
282
+ scope="local",
283
+ )
284
else:
277
- logger.info(
285
+ logger.info_once(
286
"Compiling a graph for shape %s takes %.2f s",
287
runtime_shape,
288
elapsed,
289
+ scope="local",
290
)
291
292
return compiled_graph
@@ -604,10 +613,12 @@ class VllmBackend:
613
disable_cache = envs.VLLM_DISABLE_COMPILE_CACHE
614
615
if disable_cache:
607
- logger.info("vLLM's torch.compile cache is disabled.")
616
+ logger.info_once("vLLM's torch.compile cache is disabled.", scope="local")
617
else:
609
- logger.info(
610
- "Using cache directory: %s for vLLM's torch.compile", local_cache_dir
618
+ logger.info_once(
619
+ "Using cache directory: %s for vLLM's torch.compile",
620
+ local_cache_dir,
621
+ scope="local",
622
)
623
624
self.compiler_manager.initialize_cache(
@@ -620,7 +631,9 @@ class VllmBackend:
631
from .monitor import torch_compile_start_time
632
633
dynamo_time = time.time() - torch_compile_start_time
623
- logger.info("Dynamo bytecode transform time: %.2f s", dynamo_time)
634
+ logger.info_once(
635
+ "Dynamo bytecode transform time: %.2f s", dynamo_time, scope="local"
636
+ )
637
self.compilation_config.compilation_time += dynamo_time
638
639
# we control the compilation process, each instance can only be
@@ -672,7 +685,9 @@ class VllmBackend:
685
with open(graph_path, "w") as f:
686
f.write(src)
687
675
- logger.debug("Computation graph saved to %s", graph_path)
688
+ logger.debug_once(
689
+ "Computation graph saved to %s", graph_path, scope="local"
690
+ )
691
692
self._called = True
693
vllm/compilation/monitor.py
+4
-2
@@ -31,8 +31,10 @@ def start_monitoring_torch_compile(vllm_config: VllmConfig):
31
def end_monitoring_torch_compile(vllm_config: VllmConfig):
32
compilation_config: CompilationConfig = vllm_config.compilation_config
33
if compilation_config.mode == CompilationMode.VLLM_COMPILE:
34
- logger.info(
35
- "torch.compile takes %.2f s in total", compilation_config.compilation_time
34
+ logger.info_once(
35
+ "torch.compile takes %.2f s in total",
36
+ compilation_config.compilation_time,
37
+ scope="local",
38
)
39
global context_manager
40
if context_manager is not None:
vllm/distributed/device_communicators/cuda_communicator.py
+5
-6
@@ -13,7 +13,6 @@ from vllm.distributed.device_communicators.pynccl import register_nccl_symmetric
13
from vllm.distributed.device_communicators.pynccl_allocator import (
14
is_symmetric_memory_enabled,
15
)
16
-from vllm.distributed.parallel_state import is_global_first_rank
16
from vllm.logger import init_logger
17
from vllm.platforms import current_platform
18
@@ -118,11 +117,11 @@ class CudaCommunicator(DeviceCommunicatorBase):
117
else:
118
raise ValueError(f"Unknown all2all backend: {self.all2all_backend}")
119
121
- if is_global_first_rank():
122
- logger.info(
123
- "Using %s all2all manager.",
124
- self.all2all_manager.__class__.__name__,
125
- )
120
+ logger.info_once(
121
+ "Using %s all2all manager.",
122
+ self.all2all_manager.__class__.__name__,
123
+ scope="global",
124
+ )
125
126
def all_reduce(self, input_):
127
# since currently we perform copy input -> symm_input -> out-of-place AR
vllm/distributed/device_communicators/custom_all_reduce.py
+1
-1
@@ -34,7 +34,7 @@ def _can_p2p(rank: int, world_size: int) -> bool:
34
if i == rank:
35
continue
36
if envs.VLLM_SKIP_P2P_CHECK:
37
- logger.info("Skipping P2P check and trusting the driver's P2P report.")
37
+ logger.debug("Skipping P2P check and trusting the driver's P2P report.")
38
return torch.cuda.can_device_access_peer(rank, i)
39
if not gpu_p2p_access_check(rank, i):
40
return False
vllm/distributed/device_communicators/pynccl.py
+3
-1
@@ -108,7 +108,9 @@ class PyNcclCommunicator:
108
if self.rank == 0:
109
# get the unique id from NCCL
110
self.unique_id = self.nccl.ncclGetUniqueId()
111
- logger.info("vLLM is using nccl==%s", self.nccl.ncclGetVersion())
111
+ logger.info_once(
112
+ "vLLM is using nccl==%s", self.nccl.ncclGetVersion(), scope="local"
113
+ )
114
else:
115
# construct an empty unique id
116
self.unique_id = ncclUniqueId()
vllm/distributed/device_communicators/shm_broadcast.py
+1
-1
@@ -312,7 +312,7 @@ class MessageQueue:
312
remote_addr_ipv6=remote_addr_ipv6,
313
)
314
315
- logger.info("vLLM message queue communication handle: %s", self.handle)
315
+ logger.debug("vLLM message queue communication handle: %s", self.handle)
316
317
def export_handle(self) -> Handle:
318
return self.handle
vllm/distributed/parallel_state.py
+25
-2
@@ -1157,7 +1157,7 @@ def init_distributed_environment(
1157
ip = parallel_config.data_parallel_master_ip
1158
port = parallel_config.get_next_dp_init_port()
1159
distributed_init_method = get_distributed_init_method(ip, port)
1160
- logger.info(
1160
+ logger.debug(
1161
"Adjusting world_size=%d rank=%d distributed_init_method=%s for DP",
1162
world_size,
1163
rank,
@@ -1322,7 +1322,7 @@ def initialize_model_parallel(
1322
group_ranks, get_world_group().local_rank, backend, group_name="ep"
1323
)
1324
1325
- logger.info(
1325
+ logger.info_once(
1326
"rank %s in world size %s is assigned as "
1327
"DP rank %s, PP rank %s, TP rank %s, EP rank %s",
1328
rank,
@@ -1625,6 +1625,29 @@ def is_global_first_rank() -> bool:
1625
return True
1626
1627
1628
+def is_local_first_rank() -> bool:
1629
+ """
1630
+ Check if the current process is the first local rank (rank 0 on its node).
1631
+ """
1632
+ try:
1633
+ # prefer the initialized world group if available
1634
+ global _WORLD
1635
+ if _WORLD is not None:
1636
+ return _WORLD.local_rank == 0
1637
+
1638
+ if not torch.distributed.is_initialized():
1639
+ return True
1640
+
1641
+ # fallback to environment-provided local rank if available
1642
+ # note: envs.LOCAL_RANK is set when using env:// launchers (e.g., torchrun)
1643
+ try:
1644
+ return int(envs.LOCAL_RANK) == 0 # type: ignore[arg-type]
1645
+ except Exception:
1646
+ return torch.distributed.get_rank() == 0
1647
+ except Exception:
1648
+ return True
1649
+
1650
+
1651
def _node_count(pg: ProcessGroup | StatelessProcessGroup) -> int:
1652
"""
1653
Returns the total number of nodes in the process group.
vllm/logger.py
+40
-13
@@ -13,7 +13,7 @@ from logging import Logger
13
from logging.config import dictConfig
14
from os import path
15
from types import MethodType
16
-from typing import Any, cast
16
+from typing import Any, Literal, cast
17
18
import vllm.envs as envs
19
@@ -59,20 +59,37 @@ DEFAULT_LOGGING_CONFIG = {
59
60
@lru_cache
61
def _print_debug_once(logger: Logger, msg: str, *args: Hashable) -> None:
62
- # Set the stacklevel to 2 to print the original caller's line info
63
- logger.debug(msg, *args, stacklevel=2)
62
+ # Set the stacklevel to 3 to print the original caller's line info
63
+ logger.debug(msg, *args, stacklevel=3)
64
65
66
@lru_cache
67
def _print_info_once(logger: Logger, msg: str, *args: Hashable) -> None:
68
- # Set the stacklevel to 2 to print the original caller's line info
69
- logger.info(msg, *args, stacklevel=2)
68
+ # Set the stacklevel to 3 to print the original caller's line info
69
+ logger.info(msg, *args, stacklevel=3)
70
71
72
@lru_cache
73
def _print_warning_once(logger: Logger, msg: str, *args: Hashable) -> None:
74
- # Set the stacklevel to 2 to print the original caller's line info
75
- logger.warning(msg, *args, stacklevel=2)
74
+ # Set the stacklevel to 3 to print the original caller's line info
75
+ logger.warning(msg, *args, stacklevel=3)
76
+
77
+
78
+LogScope = Literal["process", "global", "local"]
79
+
80
+
81
+def _should_log_with_scope(scope: LogScope) -> bool:
82
+ """Decide whether to log based on scope"""
83
+ if scope == "global":
84
+ from vllm.distributed.parallel_state import is_global_first_rank
85
+
86
+ return is_global_first_rank()
87
+ if scope == "local":
88
+ from vllm.distributed.parallel_state import is_local_first_rank
89
+
90
+ return is_local_first_rank()
91
+ # default "process" scope: always log
92
+ return True
93
94
95
class _VllmLogger(Logger):
@@ -84,33 +101,43 @@ class _VllmLogger(Logger):
101
`intel_extension_for_pytorch.utils._logger`.
102
"""
103
87
- def debug_once(self, msg: str, *args: Hashable) -> None:
104
+ def debug_once(
105
+ self, msg: str, *args: Hashable, scope: LogScope = "process"
106
+ ) -> None:
107
"""
108
As [`debug`][logging.Logger.debug], but subsequent calls with
109
the same message are silently dropped.
110
"""
111
+ if not _should_log_with_scope(scope):
112
+ return
113
_print_debug_once(self, msg, *args)
114
94
- def info_once(self, msg: str, *args: Hashable) -> None:
115
+ def info_once(self, msg: str, *args: Hashable, scope: LogScope = "process") -> None:
116
"""
117
As [`info`][logging.Logger.info], but subsequent calls with
118
the same message are silently dropped.
119
"""
120
+ if not _should_log_with_scope(scope):
121
+ return
122
_print_info_once(self, msg, *args)
123
101
- def warning_once(self, msg: str, *args: Hashable) -> None:
124
+ def warning_once(
125
+ self, msg: str, *args: Hashable, scope: LogScope = "process"
126
+ ) -> None:
127
"""
128
As [`warning`][logging.Logger.warning], but subsequent calls with
129
the same message are silently dropped.
130
"""
131
+ if not _should_log_with_scope(scope):
132
+ return
133
_print_warning_once(self, msg, *args)
134
135
136
# Pre-defined methods mapping to avoid repeated dictionary creation
137
_METHODS_TO_PATCH = {
111
- "debug_once": _print_debug_once,
112
- "info_once": _print_info_once,
113
- "warning_once": _print_warning_once,
138
+ "debug_once": _VllmLogger.debug_once,
139
+ "info_once": _VllmLogger.info_once,
140
+ "warning_once": _VllmLogger.warning_once,
141
}
142
143
vllm/model_executor/layers/fused_moe/layer.py
+4
-2
@@ -368,11 +368,13 @@ class UnquantizedFusedMoEMethod(FusedMoEMethodBase, CustomOp):
368
logger.info_once(
369
"FlashInfer CUTLASS MoE is available for EP"
370
" but not enabled, consider setting"
371
- " VLLM_USE_FLASHINFER_MOE_FP16=1 to enable it."
371
+ " VLLM_USE_FLASHINFER_MOE_FP16=1 to enable it.",
372
+ scope="local",
373
)
374
elif self.moe.moe_parallel_config.dp_size > 1:
375
logger.info_once(
375
- "FlashInfer CUTLASS MoE is currently not available for DP."
376
+ "FlashInfer CUTLASS MoE is currently not available for DP.",
377
+ scope="local",
378
)
379
self.flashinfer_cutlass_moe = None # type: ignore
380
vllm/model_executor/model_loader/default_loader.py
+2
-1
@@ -311,9 +311,10 @@ class DefaultModelLoader(BaseModelLoader):
311
loaded_weights = load_weights_and_online_quantize(self, model, model_config)
312
313
self.counter_after_loading_weights = time.perf_counter()
314
- logger.info(
314
+ logger.info_once(
315
"Loading weights took %.2f seconds",
316
self.counter_after_loading_weights - self.counter_before_loading_weights,
317
+ scope="local",
318
)
319
# We only enable strict check for non-quantized models
320
# that have loaded weights tracking currently.
vllm/model_executor/model_loader/weight_utils.py
+1
-1
@@ -416,7 +416,7 @@ def download_weights_from_hf(
416
e,
417
)
418
419
- logger.info("Using model weights format %s", allow_patterns)
419
+ logger.debug("Using model weights format %s", allow_patterns)
420
# Use file lock to prevent multiple processes from
421
# downloading the same model weights at the same time.
422
with get_lock(model_name_or_path, cache_dir):
vllm/platforms/__init__.py
+4
-2
@@ -222,10 +222,12 @@ def resolve_current_platform_cls_qualname() -> str:
222
)
223
elif len(activated_builtin_plugins) == 1:
224
platform_cls_qualname = builtin_platform_plugins[activated_builtin_plugins[0]]()
225
- logger.info("Automatically detected platform %s.", activated_builtin_plugins[0])
225
+ logger.debug(
226
+ "Automatically detected platform %s.", activated_builtin_plugins[0]
227
+ )
228
else:
229
platform_cls_qualname = "vllm.platforms.interface.UnspecifiedPlatform"
228
- logger.info("No platform detected, vLLM is running on UnspecifiedPlatform")
230
+ logger.debug("No platform detected, vLLM is running on UnspecifiedPlatform")
231
return platform_cls_qualname
232
233
vllm/platforms/cuda.py
+3
-1
@@ -298,7 +298,9 @@ class CudaPlatformBase(Platform):
298
)
299
300
if use_cutlassmla:
301
- logger.info_once("Using Cutlass MLA backend on V1 engine.")
301
+ logger.info_once(
302
+ "Using Cutlass MLA backend on V1 engine.", scope="local"
303
+ )
304
return "vllm.v1.attention.backends.mla.cutlass_mla.CutlassMLABackend"
305
if use_flashinfermla:
306
from vllm.v1.attention.backends.utils import set_kv_cache_layout
vllm/utils/gc_utils.py
+1
-1
@@ -37,7 +37,7 @@ class GCDebugConfig:
37
except Exception:
38
self.enabled = False
39
logger.error("Failed to parse VLLM_GC_DEBUG(%s)", envs.VLLM_GC_DEBUG)
40
- logger.info("GC Debug Config. %s", str(self))
40
+ logger.debug("GC Debug Config. %s", str(self))
41
42
def __repr__(self) -> str:
43
return f"enabled:{self.enabled},top_objects:{self.top_objects}"
vllm/v1/core/kv_cache_utils.py
+1
-1
@@ -1226,7 +1226,7 @@ def _report_kv_cache_config(
1226
vllm_config.parallel_config.decode_context_parallel_size,
1227
)
1228
num_tokens_str = f"{num_tokens:,}"
1229
- logger.info("GPU KV cache size: %s tokens", num_tokens_str)
1229
+ logger.info_once("GPU KV cache size: %s tokens", num_tokens_str, scope="local")
1230
max_model_len_str = f"{vllm_config.model_config.max_model_len:,}"
1231
max_concurrency = get_max_concurrency_for_kv_cache_config(
1232
vllm_config, kv_cache_config
vllm/v1/engine/core.py
+4
-4
@@ -19,7 +19,6 @@ import zmq
19
20
from vllm.config import ParallelConfig, VllmConfig
21
from vllm.distributed import stateless_destroy_torch_distributed_process_group
22
-from vllm.distributed.parallel_state import is_global_first_rank
22
from vllm.envs import enable_envs_cache
23
from vllm.logger import init_logger
24
from vllm.logging_utils.dump_input import dump_engine_exception
@@ -90,7 +89,7 @@ class EngineCore:
89
load_general_plugins()
90
91
self.vllm_config = vllm_config
93
- if is_global_first_rank():
92
+ if vllm_config.parallel_config.data_parallel_rank == 0:
93
logger.info(
94
"Initializing a V1 LLM engine (v%s) with config: %s",
95
VLLM_VERSION,
@@ -235,9 +234,10 @@ class EngineCore:
234
self.model_executor.initialize_from_config(kv_cache_configs)
235
236
elapsed = time.time() - start
238
- logger.info(
237
+ logger.info_once(
238
("init engine (profile, create kv cache, warmup model) took %.2f seconds"),
239
elapsed,
240
+ scope="local",
241
)
242
return num_gpu_blocks, num_cpu_blocks, scheduler_kv_cache_config
243
@@ -713,7 +713,7 @@ class EngineCoreProc(EngineCore):
713
)
714
715
# Receive initialization message.
716
- logger.info("Waiting for init message from front-end.")
716
+ logger.debug("Waiting for init message from front-end.")
717
if not handshake_socket.poll(timeout=HANDSHAKE_TIMEOUT_MINS * 60_000):
718
raise RuntimeError(
719
"Did not receive response from front-end "
vllm/v1/metrics/loggers.py
+1
-1
@@ -215,7 +215,7 @@ class LoggingStatLogger(StatLoggerBase):
215
216
def log_engine_initialized(self):
217
if self.vllm_config.cache_config.num_gpu_blocks:
218
- logger.info(
218
+ logger.debug(
219
"Engine %03d: vllm cache_config_info with initialization "
220
"after num_gpu_blocks is: %d",
221
self.engine_index,
vllm/v1/sample/ops/topk_topp_sampler.py
+4
-1
@@ -33,7 +33,10 @@ class TopKTopPSampler(nn.Module):
33
):
34
if envs.VLLM_USE_FLASHINFER_SAMPLER:
35
# Users must opt in explicitly via VLLM_USE_FLASHINFER_SAMPLER=1.
36
- logger.info_once("Using FlashInfer for top-p & top-k sampling.")
36
+ logger.info_once(
37
+ "Using FlashInfer for top-p & top-k sampling.",
38
+ scope="global",
39
+ )
40
self.forward = self.forward_cuda
41
else:
42
logger.debug_once(
vllm/v1/worker/dp_utils.py
+7
-7
@@ -6,7 +6,7 @@ import torch
6
import torch.distributed as dist
7
8
from vllm.config import ParallelConfig
9
-from vllm.distributed.parallel_state import get_dp_group, is_global_first_rank
9
+from vllm.distributed.parallel_state import get_dp_group
10
from vllm.logger import init_logger
11
from vllm.v1.worker.ubatch_utils import (
12
UBatchSlices,
@@ -132,12 +132,12 @@ def _synchronize_dp_ranks(
132
should_ubatch = _post_process_ubatch(tensor)
133
134
if should_ubatch and not should_dp_pad:
135
- if is_global_first_rank():
136
- logger.debug(
137
- "Microbatching has been triggered and requires DP padding. "
138
- "Enabling DP padding even though it has been explicitly "
139
- "disabled."
140
- )
135
+ logger.debug_once(
136
+ "Microbatching has been triggered and requires DP padding. "
137
+ "Enabling DP padding even though it has been explicitly "
138
+ "disabled.",
139
+ scope="global",
140
+ )
141
should_dp_pad = True
142
143
# Pad all DP ranks up to the maximum token count across ranks if
vllm/v1/worker/gpu_model_runner.py
+9
-3
@@ -2850,7 +2850,11 @@ class GPUModelRunner(LoRAModelRunnerMixin, KVConnectorModelRunnerMixin):
2850
Args:
2851
eep_scale_up: the model loading is for elastic EP scale up.
2852
"""
2853
- logger.info("Starting to load model %s...", self.model_config.model)
2853
+ logger.info_once(
2854
+ "Starting to load model %s...",
2855
+ self.model_config.model,
2856
+ scope="global",
2857
+ )
2858
if eep_scale_up:
2859
from vllm.distributed.parallel_state import get_ep_group
2860
@@ -2911,10 +2915,11 @@ class GPUModelRunner(LoRAModelRunnerMixin, KVConnectorModelRunnerMixin):
2915
self.model.set_aux_hidden_state_layers(aux_layers)
2916
time_after_load = time.perf_counter()
2917
self.model_memory_usage = m.consumed_memory
2914
- logger.info(
2918
+ logger.info_once(
2919
"Model loading took %.4f GiB and %.6f seconds",
2920
self.model_memory_usage / GiB_bytes,
2921
time_after_load - time_before_load,
2922
+ scope="local",
2923
)
2924
prepare_communication_buffer_for_model(self.model)
2925
@@ -3838,10 +3843,11 @@ class GPUModelRunner(LoRAModelRunnerMixin, KVConnectorModelRunnerMixin):
3843
elapsed_time = end_time - start_time
3844
cuda_graph_size = start_free_gpu_memory - end_free_gpu_memory
3845
# This usually takes 5~20 seconds.
3841
- logger.info(
3846
+ logger.info_once(
3847
"Graph capturing finished in %.0f secs, took %.2f GiB",
3848
elapsed_time,
3849
cuda_graph_size / (1 << 30),
3850
+ scope="local",
3851
)
3852
return cuda_graph_size
3853
vllm/v1/worker/gpu_worker.py
+6
-2
@@ -20,7 +20,10 @@ from vllm.distributed import (
20
set_custom_all_reduce,
21
)
22
from vllm.distributed.kv_transfer import ensure_kv_transfer_initialized
23
-from vllm.distributed.parallel_state import get_pp_group, get_tp_group
23
+from vllm.distributed.parallel_state import (
24
+ get_pp_group,
25
+ get_tp_group,
26
+)
27
from vllm.logger import init_logger
28
from vllm.lora.request import LoRARequest
29
from vllm.model_executor import set_random_seed
@@ -334,9 +337,10 @@ class Worker(WorkerBase):
337
GiB(free_gpu_memory - unrequested_memory),
338
)
339
logger.debug(profile_result)
337
- logger.info(
340
+ logger.info_once(
341
"Available KV cache memory: %.2f GiB",
342
GiB(self.available_kv_cache_memory_bytes),
343
+ scope="local",
344
)
345
gc.collect()
346