Skip to content

Commit f05cc98

Browse files
committed
[Fix] fix naming style and remove registry
1 parent 5438839 commit f05cc98

File tree

29 files changed

+260
-531
lines changed

29 files changed

+260
-531
lines changed

MANIFEST.in

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
include LICENSE
2-
include pyproject.toml
31
include CMakeLists.txt
4-
include requirements.txt
5-
include setup.py
6-
7-
recursive-include examples *
8-
recursive-include benchmarks *
2+
graft ucm
3+
graft examples
4+
graft benchmarks

docs/source/developer-guide/add_metrics.md

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ UCM supports custom metrics with bidirectional updates from both Python and C++
33

44
## Architecture Overview
55
The metrics consists of these components below:
6-
- **metrics** : Central stats registry that manages all metric lifecycle operations (registration, creation, updates, queries)
7-
- **observability.py** : Prometheus integration layer that handles metric exposition and multiprocess collection
6+
- **monitor** : Central stats registry that manages all metric lifecycle operations (registration, creation, updates, queries)
7+
- **observability.py** : Prometheus integration layer that handles metric exposition
88
- **metrics_config.yaml** : Declarative configuration that defines which custom metrics to register and their properties
99

1010
## Getting Started
@@ -31,7 +31,7 @@ prometheus:
3131

3232
# Gauge metrics configuration
3333
gauges:
34-
- name: "lookup_hit_rate"
34+
- name: "external_lookup_hit_rate"
3535
documentation: "Hit rate of ucm lookup requests"
3636
multiprocess_mode: "livemostrecent"
3737

@@ -43,15 +43,14 @@ prometheus:
4343
```
4444
4545
### Use Monitor APIs to Update Stats
46-
The monitor provides a unified interface for metric operations. Note that the workflow requires registering a stats class before creating an instance.
46+
The monitor provides a unified interface for metric operations. Users only need to create stats and update them, while the observability component is responsible for fetching the stats and pushing them to Prometheus.
4747
:::::{tab-set}
4848
:sync-group: install
4949
5050
::::{tab-item} Python side interfaces
5151
:selected:
5252
:sync: py
5353
**Lifecycle Methods**
54-
- `register_istats(name, py::object)`: Register a new stats class implementation.
5554
- `create_stats(name)`: Create and initialize a registered stats object.
5655

5756
**Operation Methods**
@@ -64,11 +63,8 @@ The monitor provides a unified interface for metric operations. Note that the wo
6463

6564
**Example:** Using built-in ConnStats
6665
```python
67-
from ucm.integration.vllm.conn_stats import ConnStats
6866
from ucm.shared.metrics import ucmmonitor
6967
70-
conn_stats = ConnStats(name="ConnStats")
71-
ucmmonitor.register_stats("ConnStats", conn_stats) # Register stats
7268
ucmmonitor.create_stats("ConnStats") # Create a stats obj
7369
7470
# Update stats
@@ -85,7 +81,6 @@ See more detailed example in [test case](https://github.com/ModelEngine-Group/un
8581
::::{tab-item} C++ side interfaces
8682
:sync: cc
8783
**Lifecycle Methods**
88-
- `RegistStats(std::string name, Creator creator)`: Register a new stats class implementation.
8984
- `CreateStats(const std::string& name)`: Create and initialize a registered stats object.
9085

9186
**Operation Methods**
@@ -102,10 +97,8 @@ UCM supports custom metrics by following steps:
10297
```c++
10398
target_link_libraries(xxxstore PUBLIC storeinfra monitor_static)
10499
```
105-
- Step 2: Inheriting from the IStats class to implement custom stats classes
106-
- Step 3: Register stats class to monitor
107-
- Step 4: Create stats object in monitor
108-
- Step 5: Update or get stats info using operation methods
100+
- Step 2: Create stats object using function **CreateStats**
101+
- Step 3: Update using function **UpdateStats**
109102

110103
See more detailed example in [test case](https://github.com/ModelEngine-Group/unified-cache-management/tree/develop/ucm/shared/test/case).
111104

pyproject.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
[build-system]
2-
requires = ["setuptools>=45", "wheel", "cmake", "torch", "pybind11"]
2+
requires = [
3+
"setuptools>=64",
4+
"cmake>=3.18",
5+
"wheel",
6+
]
37
build-backend = "setuptools.build_meta"
48

59
[project]
610
name = "uc-manager"
7-
authors = [{name = "UCM Team"}]
11+
authors = [{name = "Unified Cache Team"}]
812
license = { file="LICENSE" }
913
readme = "README.md"
1014
description = "Persist and reuse KV Cache to speedup your LLM."

setup.py

Lines changed: 40 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -23,168 +23,92 @@
2323
#
2424

2525
import os
26-
import shutil
2726
import subprocess
2827
import sys
29-
import sysconfig
30-
import warnings
31-
from glob import glob
3228

33-
import pybind11
34-
import torch
35-
import torch.utils.cpp_extension
3629
from setuptools import Extension, find_packages, setup
3730
from setuptools.command.build_ext import build_ext
3831

39-
# Suppress warnings about packages absent from packages configuration
40-
# These are expected for C++ source directories, test directories, etc.
41-
warnings.filterwarnings(
42-
"ignore", message=".*Package.*is absent from the `packages` configuration.*"
43-
)
44-
4532
ROOT_DIR = os.path.abspath(os.path.dirname(__file__))
4633
PLATFORM = os.getenv("PLATFORM")
47-
4834
ENABLE_SPARSE = os.getenv("ENABLE_SPARSE")
4935

5036

51-
def _enable_sparse() -> bool:
37+
def enable_sparse() -> bool:
5238
return ENABLE_SPARSE is not None and ENABLE_SPARSE.lower() == "true"
5339

5440

55-
def _is_cuda() -> bool:
56-
return PLATFORM == "cuda" or (hasattr(torch, "cuda") and torch.cuda.is_available())
57-
58-
59-
def _is_maca() -> bool:
60-
return PLATFORM == "maca"
41+
def is_editable_mode() -> bool:
42+
commands = [arg.lower() for arg in sys.argv]
43+
return "develop" in commands or "--editable" in commands or "-e" in commands
6144

6245

6346
class CMakeExtension(Extension):
64-
def __init__(self, name: str, sourcedir: str = ""):
47+
def __init__(self, name: str, source_dir: str = ""):
6548
super().__init__(name, sources=[])
66-
self.sourcedir = os.path.abspath(sourcedir)
49+
self.cmake_file_path = os.path.abspath(source_dir)
6750

6851

6952
class CMakeBuild(build_ext):
7053
def run(self):
54+
build_dir = os.path.abspath(self.build_temp)
55+
os.makedirs(build_dir, exist_ok=True)
56+
7157
for ext in self.extensions:
7258
self.build_cmake(ext)
7359

74-
self._copy_so_files_to_build_lib()
75-
7660
def build_cmake(self, ext: CMakeExtension):
77-
build_dir = self.build_temp
78-
os.makedirs(build_dir, exist_ok=True)
61+
build_dir = os.path.abspath(self.build_temp)
62+
install_dir = os.path.abspath(self.build_lib)
63+
if is_editable_mode:
64+
install_dir = ext.cmake_file_path
7965

8066
cmake_args = [
81-
"cmake",
8267
"-DCMAKE_BUILD_TYPE=Release",
8368
f"-DPYTHON_EXECUTABLE={sys.executable}",
69+
f"-DCMAKE_INSTALL_PREFIX={install_dir}",
8470
]
8571

86-
torch_cmake_prefix = torch.utils.cmake_prefix_path
87-
pybind11_cmake_dir = pybind11.get_cmake_dir()
72+
if enable_sparse():
73+
cmake_args += ["-DBUILD_UCM_SPARSE=ON"]
74+
75+
match PLATFORM:
76+
case "cuda":
77+
cmake_args += ["-DRUNTIME_ENVIRONMENT=cuda"]
78+
case "ascend":
79+
cmake_args += ["-DRUNTIME_ENVIRONMENT=ascend"]
80+
case "musa":
81+
cmake_args += ["-DRUNTIME_ENVIRONMENT=musa"]
82+
case "maca":
83+
cmake_args += ["-DRUNTIME_ENVIRONMENT=maca"]
84+
cmake_args += ["-DBUILD_UCM_SPARSE=OFF"]
85+
case _:
86+
cmake_args += ["-DRUNTIME_ENVIRONMENT=simu"]
87+
cmake_args += ["-DBUILD_UCM_SPARSE=OFF"]
8888

89-
cmake_prefix_paths = [torch_cmake_prefix, pybind11_cmake_dir]
90-
cmake_args.append(f"-DCMAKE_PREFIX_PATH={';'.join(cmake_prefix_paths)}")
91-
92-
torch_includes = torch.utils.cpp_extension.include_paths()
93-
python_include = sysconfig.get_path("include")
94-
pybind11_include = pybind11.get_include()
95-
96-
all_includes = torch_includes + [python_include, pybind11_include]
97-
cmake_include_string = ";".join(all_includes)
98-
cmake_args.append(f"-DEXTERNAL_INCLUDE_DIRS={cmake_include_string}")
99-
100-
if _is_cuda():
101-
cmake_args.append("-DRUNTIME_ENVIRONMENT=cuda")
102-
else:
103-
cmake_args.append("-DRUNTIME_ENVIRONMENT=ascend")
104-
105-
if _enable_sparse():
106-
cmake_args.append("-DBUILD_UCM_SPARSE=ON")
107-
108-
cmake_args.append(ext.sourcedir)
109-
110-
print(f"[INFO] Building {ext.name} module with CMake")
111-
print(f"[INFO] Source directory: {ext.sourcedir}")
112-
print(f"[INFO] Build directory: {build_dir}")
113-
print(f"[INFO] CMake command: {' '.join(cmake_args)}")
114-
115-
subprocess.check_call(cmake_args, cwd=build_dir)
89+
subprocess.check_call(
90+
["cmake", *cmake_args, ext.cmake_file_path], cwd=build_dir
91+
)
11692
subprocess.check_call(
11793
["cmake", "--build", ".", "--config", "Release", "--", "-j8"],
11894
cwd=build_dir,
11995
)
12096

121-
def _copy_so_files_to_build_lib(self):
122-
"""Copy .so files from source directories to build_lib for installation."""
123-
if not hasattr(self, "build_lib") or not self.build_lib:
124-
return
125-
126-
packages = _get_packages()
127-
copied_count = 0
128-
129-
for package in packages:
130-
# Source directory where CMake outputs .so files
131-
source_package_dir = os.path.join(ROOT_DIR, package.replace(".", os.sep))
132-
133-
# Destination in build_lib
134-
build_package_dir = os.path.join(
135-
self.build_lib, package.replace(".", os.sep)
136-
)
137-
138-
# Find all .so files in the source package directory
139-
so_files = glob(os.path.join(source_package_dir, "*.so"))
140-
141-
if so_files:
142-
# Ensure destination directory exists
143-
os.makedirs(build_package_dir, exist_ok=True)
144-
145-
# Copy each .so file
146-
for so_file in so_files:
147-
dest_file = os.path.join(
148-
build_package_dir, os.path.basename(so_file)
149-
)
150-
shutil.copy2(so_file, dest_file)
151-
copied_count += 1
152-
print(
153-
f"[INFO] Copied {os.path.basename(so_file)} to {build_package_dir}"
154-
)
155-
156-
if copied_count > 0:
157-
print(f"[INFO] Successfully copied {copied_count} .so file(s) to build_lib")
158-
else:
159-
print(
160-
"[WARNING] No .so files found to copy. Extensions may not have been built."
161-
)
162-
163-
164-
def _get_packages():
165-
"""Discover Python packages, optionally filtering out sparse-related ones."""
166-
sparse_enabled = _enable_sparse()
167-
exclude_patterns = []
168-
if not sparse_enabled:
169-
exclude_patterns.append("ucm.sparse*")
170-
171-
packages = find_packages(exclude=exclude_patterns)
172-
return packages
173-
174-
175-
ext_modules = []
176-
ext_modules.append(CMakeExtension(name="ucm", sourcedir=ROOT_DIR))
97+
subprocess.check_call(
98+
["cmake", "--install", ".", "--config", "Release", "--component", "ucm"],
99+
cwd=build_dir,
100+
)
177101

178-
packages = _get_packages()
179102

180103
setup(
181104
name="uc-manager",
182105
version="0.1.2",
183106
description="Unified Cache Management",
184107
author="Unified Cache Team",
185-
packages=packages,
108+
packages=find_packages(),
186109
python_requires=">=3.10",
187-
ext_modules=ext_modules,
110+
ext_modules=[CMakeExtension(name="ucm", source_dir=ROOT_DIR)],
188111
cmdclass={"build_ext": CMakeBuild},
189112
zip_safe=False,
113+
include_package_data=False,
190114
)

ucm/integration/vllm/conn_stats.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

ucm/integration/vllm/patch/patch_funcs/v092/vllm_patch.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -553,14 +553,14 @@ def _patch_scheduler() -> None:
553553

554554
from ucm.sparse.base import INVALID_SLOT, UcmSparseRole
555555
from ucm.sparse.state import ensure_ucm_sparse_initialized, get_ucm_sparse
556+
from ucm.utils import Config
556557

557558
def init_ucm_sparse(self):
558559
self.ucm_sparse = None
559560
if self.vllm_config.kv_transfer_config is not None:
560-
if (
561-
"ucm_sparse_config"
562-
in self.vllm_config.kv_transfer_config.kv_connector_extra_config
563-
):
561+
ucm_config = Config(self.vllm_config.kv_transfer_config)
562+
ucm_sparse_config = ucm_config.get_config().get("ucm_sparse_config")
563+
if ucm_sparse_config:
564564
ensure_ucm_sparse_initialized(
565565
self.vllm_config, role=UcmSparseRole.SCHEDULER
566566
)

ucm/integration/vllm/ucm_connector.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from vllm.platforms import current_platform
1818
from vllm.v1.core.sched.output import SchedulerOutput
1919

20-
from ucm.integration.vllm.conn_stats import ConnStats
2120
from ucm.logger import init_logger
2221
from ucm.observability import UCMStatsLogger
2322
from ucm.shared.metrics import ucmmonitor
@@ -173,8 +172,6 @@ def __init__(self, vllm_config: "VllmConfig", role: KVConnectorRole):
173172

174173
self.metrics_config = self.launch_config.get("metrics_config_path", "")
175174
if self.metrics_config:
176-
conn_stats = ConnStats(name="ConnStats")
177-
ucmmonitor.register_stats("ConnStats", conn_stats)
178175
ucmmonitor.create_stats("ConnStats")
179176
self.stats_logger = UCMStatsLogger(
180177
vllm_config.model_config.served_model_name,

0 commit comments

Comments
 (0)