Skip to content

Commit 0f3630d

Browse files
fix
1 parent 9cf8751 commit 0f3630d

File tree

3 files changed

+92
-63
lines changed

3 files changed

+92
-63
lines changed

lightllm/server/api_start.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from .router.manager import start_router_process
1717
from lightllm.utils.process_check import is_process_active
1818
from lightllm.utils.multinode_utils import send_and_receive_node_ip
19-
from lightllm.utils.shm_size_check import check_shm_size, start_shm_size_warning_thread
19+
from lightllm.utils.shm_size_check import check_recommended_shm_size
2020

2121
logger = init_logger(__name__)
2222

@@ -64,15 +64,7 @@ def signal_handler(sig, frame):
6464
def normal_or_p_d_start(args):
6565
set_unique_server_name(args)
6666

67-
shm_size, require_shm_size, is_shm_sufficient = check_shm_size(args)
68-
if not args.disable_shm_warning and not is_shm_sufficient:
69-
start_shm_size_warning_thread(shm_size, require_shm_size)
70-
else:
71-
logger.info(
72-
f"SHM check: Available={shm_size:.2f} GB,",
73-
f"Required={require_shm_size:.2f} GB.",
74-
f"Sufficient: {is_shm_sufficient}",
75-
)
67+
check_recommended_shm_size(args)
7668

7769
if args.enable_mps:
7870
from lightllm.utils.device_utils import enable_mps

lightllm/utils/config_utils.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,23 @@ def get_config_json(model_path: str):
1313
return json_obj
1414

1515

16+
def get_hidden_size(model_path: str):
17+
# try to get hidden_size in config.json
18+
config_json = get_config_json(model_path)
19+
try:
20+
hidden_size = config_json["hidden_size"]
21+
except:
22+
# for some multimodal model
23+
try:
24+
hidden_size = config_json.get("llm_config", {}).get("hidden_size")
25+
except:
26+
hidden_size = config_json.get("text_config", {}).get("hidden_size")
27+
if not isinstance(hidden_size, int):
28+
logger.error("cannot get hidden size from config.json, return None instead")
29+
return None
30+
return hidden_size
31+
32+
1633
def get_eos_token_ids(model_path: str):
1734
config_json = get_config_json(model_path)
1835
try:

lightllm/utils/shm_size_check.py

Lines changed: 73 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,54 @@
77
import signal
88
from lightllm.server.core.objs.out_token_circlequeue import LIGHTLLM_OUT_TOKEN_QUEUE_SIZE, LIGHTLLM_TOKEN_MAX_BYTES
99
from lightllm.server.core.objs.req import ChunkedPrefillReq, TokenHealingReq
10+
from lightllm.server.multimodal_params import ImageItem
1011
from lightllm.server.tokenizer import get_tokenizer
11-
from lightllm.utils.config_utils import get_config_json
12+
from lightllm.utils.config_utils import get_hidden_size
1213
from lightllm.utils.log_utils import init_logger
1314
from transformers import AutoTokenizer
1415

1516
logger = init_logger(__name__)
1617

1718

18-
def get_shm_size_gb():
19+
def check_recommended_shm_size(args):
20+
shm_size, recommended_shm_size, is_shm_sufficient = _check_shm_size(args)
21+
if not args.disable_shm_warning and not is_shm_sufficient:
22+
_start_shm_size_warning_thread(shm_size, recommended_shm_size)
23+
else:
24+
logger.info(
25+
f"SHM check: Available={shm_size:.2f} GB,"
26+
f"Recommended={recommended_shm_size:.2f} GB."
27+
f"Sufficient: {is_shm_sufficient}",
28+
)
29+
30+
31+
def _check_shm_size(args):
32+
RED = "\033[91m"
33+
ENDC = "\033[0m"
34+
shm_size = _get_system_shm_size_gb()
35+
required_size = _get_recommended_shm_size_gb(args) # 128G
36+
if shm_size < required_size:
37+
logger.warning(f"{RED}Available shm size is less than 128G: {shm_size:.2f}G{ENDC}")
38+
return shm_size, required_size, False
39+
else: # shm_size >= required_size
40+
return shm_size, required_size, True
41+
42+
43+
def _start_shm_size_warning_thread(shm_size, required_shm_size):
44+
shm_warning_thread = threading.Thread(
45+
target=_periodic_shm_warning,
46+
args=(
47+
shm_size,
48+
required_shm_size,
49+
),
50+
daemon=True,
51+
)
52+
shm_warning_thread.start()
53+
54+
55+
def _get_system_shm_size_gb():
1956
"""
20-
获取 /dev/shm 的总大小以GB为单位
57+
获取 /dev/shm 的总大小(以GB为单位)
2158
"""
2259
try:
2360
shm_path = "/dev/shm"
@@ -34,87 +71,70 @@ def get_shm_size_gb():
3471
return 0
3572

3673

37-
def get_required_shm_size_gb(args, max_image_resolution=(3940, 2160), dtype_size=2):
74+
def _get_recommended_shm_size_gb(args, max_image_resolution=(3940, 2160), dtype_size=2):
3875
"""
39-
获取所需的 /dev/shm 大小以GB为单位
76+
获取所需的 /dev/shm 大小(以GB为单位)
4077
"""
41-
model_config = get_config_json(args.model_dir)
4278
tokenizer = get_tokenizer(args.model_dir, trust_remote_code=True)
4379

80+
# 估算input_token和logprob占用shm大小,由于是double和int64,所以固定占用8个字节
81+
input_token_logprob_size_bytes = args.running_max_req_size * 8 * 2 * args.max_req_total_len
82+
83+
# 估算Req所需的shm大小
84+
if args.token_healing_mode:
85+
req_class_size = ctypes.sizeof(TokenHealingReq)
86+
else:
87+
req_class_size = ctypes.sizeof(ChunkedPrefillReq)
88+
req_shm_size_bytes = req_class_size * args.running_max_req_size
89+
4490
if not args.enable_multimodal:
45-
# by default, 非多模态 24 GB
46-
total_required_size_gb = 24
91+
total_recommended_shm_size_gb = (req_shm_size_bytes + input_token_logprob_size_bytes) / (1024 ** 3) + 2
4792
else:
93+
# 存储图片数据所需的shm大小
4894
num_channels = 3
4995
image_width, image_height = max_image_resolution
5096
image_size_bytes = image_width * image_height * num_channels
5197

5298
# 假设加载最大分辨率图片时,通过 tokenizer 得到最多的 image_tokens
5399
if not hasattr(tokenizer, "get_image_token_length"):
54100
raise AttributeError("Tokenizer must have a 'get_image_token_length' method for multimodal models.")
55-
max_image_tokens = tokenizer.get_image_token_length(None)
101+
fake_image_item = ImageItem(
102+
type="image_size",
103+
data=max_image_resolution,
104+
)
105+
fake_image_item.image_w = fake_image_item._data[0]
106+
fake_image_item.image_h = fake_image_item._data[1]
107+
max_image_tokens = tokenizer.get_image_token_length(fake_image_item)
56108

57109
# 估算图片 token 所需的资源
58-
hidden_size = model_config.get("hidden_size")
110+
hidden_size = get_hidden_size(args.model_dir)
59111
if hidden_size is None:
60-
logger.warning("Model config not contain 'hidden_size', using 4096 by default.")
112+
logger.warning(
113+
"Model config not contain 'hidden_size', " "using 4096 by default to calculate recommended shm size."
114+
)
61115
image_token_size_bytes = max_image_tokens * 4096 * dtype_size
62116
else:
63117
image_token_size_bytes = max_image_tokens * hidden_size * dtype_size
64118

65-
# 估算Req所需的shm大小
66-
if args.token_healing_mode:
67-
req_class_size = ctypes.sizeof(TokenHealingReq)
68-
else:
69-
req_class_size = ctypes.sizeof(ChunkedPrefillReq)
70-
req_shm_size_bytes = req_class_size * args.running_max_req_size
71-
72-
# 估算OutTokenQueue所需shm大小
73-
out_token_queue_size_bytes = LIGHTLLM_TOKEN_MAX_BYTES * LIGHTLLM_OUT_TOKEN_QUEUE_SIZE
74-
75-
total_required_size = (
119+
total_recommended_shm_size_gb = (
76120
args.cache_capacity * (image_size_bytes + image_token_size_bytes)
77121
+ req_shm_size_bytes
78-
+ out_token_queue_size_bytes
122+
+ input_token_logprob_size_bytes
79123
)
80124

81-
total_required_size_gb = total_required_size / (1024 ** 3) + 2
82-
83-
return total_required_size_gb
125+
total_recommended_shm_size_gb = total_recommended_shm_size_gb / (1024 ** 3) + 2
84126

85-
86-
def check_shm_size(args):
87-
RED = "\033[91m"
88-
ENDC = "\033[0m"
89-
shm_size = get_shm_size_gb()
90-
required_size = get_required_shm_size_gb(args) # 128G
91-
if shm_size < required_size:
92-
logger.warning(f"{RED}Available shm size is less than 128G: {shm_size:.2f}G{ENDC}")
93-
return shm_size, required_size, False
94-
else: # shm_size >= required_size
95-
return shm_size, required_size, True
127+
return total_recommended_shm_size_gb
96128

97129

98-
def periodic_shm_warning(shm_size, required_shm_size):
130+
def _periodic_shm_warning(shm_size, required_shm_size):
99131
RED = "\033[91m"
100132
ENDC = "\033[0m"
101133
while True:
102134
logger.warning(
103-
f"{RED}Insufficient shared memory (SHM) available.",
104-
f"Required: {required_shm_size:.2f}G, Available: {shm_size:.2f}G.\n",
105-
"If running in Docker, you can increase SHM size with the `--shm-size` flag, ",
135+
f"{RED}Insufficient shared memory (SHM) available."
136+
f"Required: {required_shm_size:.2f}G, Available: {shm_size:.2f}G.\n"
137+
"If running in Docker, you can increase SHM size with the `--shm-size` flag, "
106138
f"like so: `docker run --shm-size=30g [your_image]`{ENDC}",
107139
)
108140
time.sleep(120) # 每 120 秒打印一次警告日志
109-
110-
111-
def start_shm_size_warning_thread(shm_size, required_shm_size):
112-
shm_warning_thread = threading.Thread(
113-
target=periodic_shm_warning,
114-
args=(
115-
shm_size,
116-
required_shm_size,
117-
),
118-
daemon=True,
119-
)
120-
shm_warning_thread.start()

0 commit comments

Comments
 (0)