Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 5 additions & 3 deletions lightllm/common/basemodel/basemodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from lightllm.common.quantization import Quantcfg
from lightllm.common.basemodel.triton_kernel.gather_token_id import gather_token, gather_token_prefill_decode_mixed
from lightllm.utils.log_utils import init_logger
from lightllm.utils.gc_utils import freeze_gc, gc_frozen_and_disabled
from lightllm.utils.dist_utils import get_dp_world_size
from lightllm.utils.envs_utils import get_env_start_args, get_llm_data_type, get_added_mtp_kv_layer_num
from lightllm.distributed.communication_op import dist_group_manager
Expand Down Expand Up @@ -127,11 +128,13 @@ def __init__(self, kvargs):

self._autotune_warmup()
self._init_padded_req()
self._init_cudagraph()
self._init_prefill_cuda_graph()
with gc_frozen_and_disabled("cudagraph-capture"):
self._init_cudagraph()
self._init_prefill_cuda_graph()
Comment on lines +131 to +133

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If CUDA graph capture is disabled (both decode and prefill CUDA graphs are disabled), entering the gc_frozen_and_disabled context manager will still trigger a full garbage collection and freeze. Since gc.collect() on a large model worker process can be quite expensive, we should conditionally wrap the initialization in gc_frozen_and_disabled only when at least one CUDA graph capture is enabled.

Suggested change
with gc_frozen_and_disabled("cudagraph-capture"):
self._init_cudagraph()
self._init_prefill_cuda_graph()
if (not self.disable_cudagraph) or get_env_start_args().enable_prefill_cudagraph:
with gc_frozen_and_disabled("cudagraph-capture"):
self._init_cudagraph()
self._init_prefill_cuda_graph()
else:
self._init_cudagraph()
self._init_prefill_cuda_graph()

self._check_max_len_infer()
torch.cuda.empty_cache()
set_model_init_status(True)
freeze_gc("model-infer-worker")
return

def _init_config(self):
Expand Down Expand Up @@ -604,7 +607,6 @@ def _decode(

@final
def _context_forward(self, infer_state: InferStateInfo):

input_embs = self.pre_infer.context_forward(infer_state.input_ids, infer_state, self.pre_post_weight)
if self.args.enable_dp_prefill_balance:
assert not self.args.enable_prefill_cudagraph, "not support now"
Expand Down
2 changes: 2 additions & 0 deletions lightllm/server/api_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from .api_lightllm import lightllm_get_score
from lightllm.utils.envs_utils import get_env_start_args, get_lightllm_websocket_max_message_size
from lightllm.utils.log_utils import init_logger
from lightllm.utils.gc_utils import freeze_gc
from lightllm.utils.error_utils import ClientDisconnected, ServerBusyError
from lightllm.server.metrics.manager import MetricClient
from lightllm.utils.envs_utils import get_unique_server_name
Expand Down Expand Up @@ -497,4 +498,5 @@ async def startup_event():
g_objs.set_args(get_env_start_args())
loop.create_task(g_objs.httpserver_manager.handle_loop())
logger.info(f"server start up ok, loop use is {asyncio.get_event_loop()}")
freeze_gc("httpserver")
return
2 changes: 2 additions & 0 deletions lightllm/server/detokenization/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import pickle
import time
from lightllm.utils.log_utils import init_logger
from lightllm.utils.gc_utils import freeze_gc
from lightllm.utils.envs_utils import get_unique_server_name

logger = init_logger(__name__)
Expand Down Expand Up @@ -179,5 +180,6 @@ def start_detokenization_process(args, pipe_writer):
pipe_writer.send(str(e))
raise
pipe_writer.send("init ok")
freeze_gc("detokenization")
manager.handle_loop()
return
2 changes: 2 additions & 0 deletions lightllm/server/router/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from lightllm.server.multi_level_kv_cache.cpu_cache_client import CpuKvCacheClient
from lightllm.server.core.objs.shm_objs_io_buffer import ShmObjsIOBuffer
from lightllm.utils.log_utils import init_logger, log_time_ready
from lightllm.utils.gc_utils import freeze_gc
from lightllm.utils.profiler import ProfilerCmd
from lightllm.server.router.token_load import TokenLoad
from lightllm.server.metrics.manager import MetricClient
Expand Down Expand Up @@ -569,5 +570,6 @@ def handle_exception(loop, context):
raise

pipe_writer.send("init ok")
freeze_gc("router")
loop.run_until_complete(router.loop_for_fwd())
return
23 changes: 23 additions & 0 deletions lightllm/utils/gc_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import gc
from contextlib import contextmanager
from lightllm.utils.log_utils import init_logger

logger = init_logger(__name__)


def freeze_gc(tag: str = "") -> None:
gc.collect()
gc.freeze()
logger.info(f"gc.freeze done ({tag}): frozen={gc.get_freeze_count()}")


@contextmanager
def gc_frozen_and_disabled(tag: str = ""):
freeze_gc(tag)
was_enabled = gc.isenabled()
gc.disable()
try:
yield
finally:
if was_enabled:
gc.enable()
Loading