lmcache-cli 0.4.5.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lmcache/__init__.py +84 -0
- lmcache/_version.py +24 -0
- lmcache/cli/__init__.py +1 -0
- lmcache/cli/commands/__init__.py +34 -0
- lmcache/cli/commands/base.py +157 -0
- lmcache/cli/commands/bench/__init__.py +557 -0
- lmcache/cli/commands/bench/engine_bench/__init__.py +1 -0
- lmcache/cli/commands/bench/engine_bench/config.py +245 -0
- lmcache/cli/commands/bench/engine_bench/interactive/__init__.py +274 -0
- lmcache/cli/commands/bench/engine_bench/interactive/config.json +10 -0
- lmcache/cli/commands/bench/engine_bench/interactive/schema.py +352 -0
- lmcache/cli/commands/bench/engine_bench/interactive/state.py +327 -0
- lmcache/cli/commands/bench/engine_bench/interactive/terminal.py +291 -0
- lmcache/cli/commands/bench/engine_bench/progress.py +145 -0
- lmcache/cli/commands/bench/engine_bench/request_sender.py +232 -0
- lmcache/cli/commands/bench/engine_bench/stats.py +275 -0
- lmcache/cli/commands/bench/engine_bench/workloads/__init__.py +153 -0
- lmcache/cli/commands/bench/engine_bench/workloads/base.py +122 -0
- lmcache/cli/commands/bench/engine_bench/workloads/long_doc_permutator.py +435 -0
- lmcache/cli/commands/bench/engine_bench/workloads/long_doc_qa.py +281 -0
- lmcache/cli/commands/bench/engine_bench/workloads/multi_round_chat.py +337 -0
- lmcache/cli/commands/bench/engine_bench/workloads/random_prefill.py +178 -0
- lmcache/cli/commands/describe.py +310 -0
- lmcache/cli/commands/kvcache.py +133 -0
- lmcache/cli/commands/mock.py +75 -0
- lmcache/cli/commands/ping.py +113 -0
- lmcache/cli/commands/query/__init__.py +155 -0
- lmcache/cli/commands/query/prompt.py +134 -0
- lmcache/cli/commands/query/request.py +357 -0
- lmcache/cli/commands/server.py +99 -0
- lmcache/cli/commands/tool/__init__.py +63 -0
- lmcache/cli/commands/tool/cache_simulator.py +113 -0
- lmcache/cli/commands/trace/__init__.py +505 -0
- lmcache/cli/commands/trace/dispatch.py +249 -0
- lmcache/cli/commands/trace/driver.py +372 -0
- lmcache/cli/commands/trace/stats.py +289 -0
- lmcache/cli/documents/lmcache.txt +11 -0
- lmcache/cli/main.py +42 -0
- lmcache/cli/metrics/__init__.py +29 -0
- lmcache/cli/metrics/formatter.py +171 -0
- lmcache/cli/metrics/handler.py +94 -0
- lmcache/cli/metrics/metrics.py +161 -0
- lmcache/cli/metrics/section.py +77 -0
- lmcache/connections.py +173 -0
- lmcache/integration/__init__.py +2 -0
- lmcache/integration/base_service_factory.py +165 -0
- lmcache/integration/request_telemetry/__init__.py +1 -0
- lmcache/integration/request_telemetry/base.py +51 -0
- lmcache/integration/request_telemetry/factory.py +113 -0
- lmcache/integration/request_telemetry/fastapi.py +109 -0
- lmcache/integration/request_telemetry/noop.py +35 -0
- lmcache/integration/sglang/__init__.py +2 -0
- lmcache/integration/sglang/sglang_adapter.py +326 -0
- lmcache/integration/sglang/utils.py +39 -0
- lmcache/integration/vllm/__init__.py +1 -0
- lmcache/integration/vllm/lmcache_connector_v1.py +213 -0
- lmcache/integration/vllm/lmcache_connector_v1_085.py +150 -0
- lmcache/integration/vllm/lmcache_mp_connector_0180.py +1072 -0
- lmcache/integration/vllm/tests/test_mm_hash_utils.py +112 -0
- lmcache/integration/vllm/utils.py +433 -0
- lmcache/integration/vllm/vllm_multi_process_adapter.py +1090 -0
- lmcache/integration/vllm/vllm_service_factory.py +339 -0
- lmcache/integration/vllm/vllm_v1_adapter.py +1713 -0
- lmcache/logging.py +107 -0
- lmcache/native_storage_ops.pyi +230 -0
- lmcache/non_cuda_equivalents.py +1424 -0
- lmcache/observability.py +1958 -0
- lmcache/storage_backend/serde/__init__.py +1 -0
- lmcache/storage_backend/serde/cachegen_basics.py +210 -0
- lmcache/storage_backend/serde/cachegen_decoder.py +207 -0
- lmcache/storage_backend/serde/cachegen_encoder.py +394 -0
- lmcache/storage_backend/serde/serde.py +75 -0
- lmcache/tools/__init__.py +1 -0
- lmcache/tools/cache_simulator/README.md +392 -0
- lmcache/tools/cache_simulator/__init__.py +1 -0
- lmcache/tools/cache_simulator/docs/simulate_example.png +0 -0
- lmcache/tools/cache_simulator/docs/sweep_example.png +0 -0
- lmcache/tools/cache_simulator/gen_bench_dataset.py +360 -0
- lmcache/tools/cache_simulator/lru_cache.py +124 -0
- lmcache/tools/cache_simulator/plot_hit_rate.py +231 -0
- lmcache/tools/cache_simulator/simulator.py +795 -0
- lmcache/tools/controller_benchmark/README.md +161 -0
- lmcache/tools/controller_benchmark/__init__.py +1 -0
- lmcache/tools/controller_benchmark/__main__.py +331 -0
- lmcache/tools/controller_benchmark/benchmark.py +660 -0
- lmcache/tools/controller_benchmark/config.py +44 -0
- lmcache/tools/controller_benchmark/constants.py +10 -0
- lmcache/tools/controller_benchmark/handlers/__init__.py +46 -0
- lmcache/tools/controller_benchmark/handlers/admit.py +52 -0
- lmcache/tools/controller_benchmark/handlers/base.py +47 -0
- lmcache/tools/controller_benchmark/handlers/deregister.py +49 -0
- lmcache/tools/controller_benchmark/handlers/evict.py +52 -0
- lmcache/tools/controller_benchmark/handlers/heartbeat.py +56 -0
- lmcache/tools/controller_benchmark/handlers/p2p_lookup.py +47 -0
- lmcache/tools/controller_benchmark/handlers/register.py +56 -0
- lmcache/tools/mp_status_viewer/__init__.py +1 -0
- lmcache/tools/mp_status_viewer/__main__.py +95 -0
- lmcache/usage_context.py +417 -0
- lmcache/utils.py +665 -0
- lmcache/v1/__init__.py +2 -0
- lmcache/v1/api_server/__init__.py +2 -0
- lmcache/v1/api_server/__main__.py +537 -0
- lmcache/v1/basic_check.py +112 -0
- lmcache/v1/cache_controller/__init__.py +9 -0
- lmcache/v1/cache_controller/commands/__init__.py +15 -0
- lmcache/v1/cache_controller/commands/base.py +35 -0
- lmcache/v1/cache_controller/commands/full_sync.py +49 -0
- lmcache/v1/cache_controller/config.py +176 -0
- lmcache/v1/cache_controller/controller_manager.py +535 -0
- lmcache/v1/cache_controller/controllers/__init__.py +11 -0
- lmcache/v1/cache_controller/controllers/full_sync_tracker.py +473 -0
- lmcache/v1/cache_controller/controllers/kv_controller.py +439 -0
- lmcache/v1/cache_controller/controllers/registration_controller.py +282 -0
- lmcache/v1/cache_controller/executor.py +463 -0
- lmcache/v1/cache_controller/frontend/static/css/style.css +201 -0
- lmcache/v1/cache_controller/frontend/static/img/logo.png +0 -0
- lmcache/v1/cache_controller/frontend/static/index.html +234 -0
- lmcache/v1/cache_controller/frontend/static/js/controller_app.js +660 -0
- lmcache/v1/cache_controller/full_sync_sender.py +475 -0
- lmcache/v1/cache_controller/locks.py +149 -0
- lmcache/v1/cache_controller/message.py +828 -0
- lmcache/v1/cache_controller/observability.py +208 -0
- lmcache/v1/cache_controller/utils.py +679 -0
- lmcache/v1/cache_controller/worker.py +665 -0
- lmcache/v1/cache_engine.py +2058 -0
- lmcache/v1/cache_interface.py +19 -0
- lmcache/v1/check/__init__.py +74 -0
- lmcache/v1/check/check_mode_gen.py +86 -0
- lmcache/v1/check/check_mode_test_l2_adapter.py +284 -0
- lmcache/v1/check/check_mode_test_remote.py +155 -0
- lmcache/v1/check/check_mode_test_storage_manager.py +142 -0
- lmcache/v1/check/utils.py +571 -0
- lmcache/v1/compute/__init__.py +2 -0
- lmcache/v1/compute/attention/__init__.py +0 -0
- lmcache/v1/compute/attention/abstract.py +39 -0
- lmcache/v1/compute/attention/flash_attn.py +129 -0
- lmcache/v1/compute/attention/flash_infer_sparse.py +284 -0
- lmcache/v1/compute/attention/metadata.py +85 -0
- lmcache/v1/compute/attention/utils.py +14 -0
- lmcache/v1/compute/blend/__init__.py +7 -0
- lmcache/v1/compute/blend/blender.py +168 -0
- lmcache/v1/compute/blend/metadata.py +34 -0
- lmcache/v1/compute/blend/utils.py +63 -0
- lmcache/v1/compute/models/__init__.py +0 -0
- lmcache/v1/compute/models/base.py +141 -0
- lmcache/v1/compute/models/llama.py +9 -0
- lmcache/v1/compute/models/qwen3.py +24 -0
- lmcache/v1/compute/models/utils.py +68 -0
- lmcache/v1/compute/positional_encoding.py +199 -0
- lmcache/v1/config.py +848 -0
- lmcache/v1/config_base.py +848 -0
- lmcache/v1/distributed/api.py +248 -0
- lmcache/v1/distributed/config.py +321 -0
- lmcache/v1/distributed/error.py +64 -0
- lmcache/v1/distributed/eviction.py +192 -0
- lmcache/v1/distributed/eviction_policy/__init__.py +21 -0
- lmcache/v1/distributed/eviction_policy/factory.py +27 -0
- lmcache/v1/distributed/eviction_policy/lru.py +244 -0
- lmcache/v1/distributed/eviction_policy/noop.py +50 -0
- lmcache/v1/distributed/internal_api.py +170 -0
- lmcache/v1/distributed/l1_manager.py +835 -0
- lmcache/v1/distributed/l2_adapters/__init__.py +67 -0
- lmcache/v1/distributed/l2_adapters/base.py +360 -0
- lmcache/v1/distributed/l2_adapters/config.py +385 -0
- lmcache/v1/distributed/l2_adapters/factory.py +205 -0
- lmcache/v1/distributed/l2_adapters/fs_l2_adapter.py +747 -0
- lmcache/v1/distributed/l2_adapters/fs_native_l2_adapter.py +167 -0
- lmcache/v1/distributed/l2_adapters/mock_l2_adapter.py +516 -0
- lmcache/v1/distributed/l2_adapters/mooncake_store_l2_adapter.py +135 -0
- lmcache/v1/distributed/l2_adapters/native_connector_l2_adapter.py +468 -0
- lmcache/v1/distributed/l2_adapters/native_plugin_l2_adapter.py +199 -0
- lmcache/v1/distributed/l2_adapters/nixl_store_dynamic_l2_adapter.py +831 -0
- lmcache/v1/distributed/l2_adapters/nixl_store_l2_adapter.py +983 -0
- lmcache/v1/distributed/l2_adapters/plugin_l2_adapter.py +210 -0
- lmcache/v1/distributed/l2_adapters/resp_l2_adapter.py +176 -0
- lmcache/v1/distributed/memory_manager.py +179 -0
- lmcache/v1/distributed/storage_controller.py +39 -0
- lmcache/v1/distributed/storage_controllers/__init__.py +43 -0
- lmcache/v1/distributed/storage_controllers/eviction_controller.py +242 -0
- lmcache/v1/distributed/storage_controllers/prefetch_controller.py +830 -0
- lmcache/v1/distributed/storage_controllers/prefetch_policy.py +193 -0
- lmcache/v1/distributed/storage_controllers/store_controller.py +452 -0
- lmcache/v1/distributed/storage_controllers/store_policy.py +213 -0
- lmcache/v1/distributed/storage_manager.py +532 -0
- lmcache/v1/event_manager.py +145 -0
- lmcache/v1/exceptions/__init__.py +16 -0
- lmcache/v1/gpu_connector/__init__.py +126 -0
- lmcache/v1/gpu_connector/gpu_connectors.py +1906 -0
- lmcache/v1/gpu_connector/gpu_ops.py +85 -0
- lmcache/v1/gpu_connector/hpu_connector.py +326 -0
- lmcache/v1/gpu_connector/mock_gpu_connector.py +67 -0
- lmcache/v1/gpu_connector/utils.py +890 -0
- lmcache/v1/gpu_connector/xpu_connectors.py +916 -0
- lmcache/v1/health_monitor/__init__.py +1 -0
- lmcache/v1/health_monitor/base.py +587 -0
- lmcache/v1/health_monitor/checks/__init__.py +1 -0
- lmcache/v1/health_monitor/checks/remote_backend_check.py +304 -0
- lmcache/v1/health_monitor/constants.py +36 -0
- lmcache/v1/internal_api_server/__init__.py +0 -0
- lmcache/v1/internal_api_server/api_registry.py +59 -0
- lmcache/v1/internal_api_server/api_server.py +120 -0
- lmcache/v1/internal_api_server/common/__init__.py +1 -0
- lmcache/v1/internal_api_server/common/env_api.py +22 -0
- lmcache/v1/internal_api_server/common/loglevel_api.py +57 -0
- lmcache/v1/internal_api_server/common/metrics_api.py +29 -0
- lmcache/v1/internal_api_server/common/periodic_thread_api.py +138 -0
- lmcache/v1/internal_api_server/common/run_script_api.py +73 -0
- lmcache/v1/internal_api_server/common/thread_api.py +63 -0
- lmcache/v1/internal_api_server/controller/__init__.py +1 -0
- lmcache/v1/internal_api_server/controller/key_stats_api.py +81 -0
- lmcache/v1/internal_api_server/controller/worker_info_api.py +136 -0
- lmcache/v1/internal_api_server/utils.py +43 -0
- lmcache/v1/internal_api_server/vllm/__init__.py +1 -0
- lmcache/v1/internal_api_server/vllm/backend_api.py +221 -0
- lmcache/v1/internal_api_server/vllm/bypass_api.py +204 -0
- lmcache/v1/internal_api_server/vllm/cache_api.py +895 -0
- lmcache/v1/internal_api_server/vllm/chunk_statistics_api.py +141 -0
- lmcache/v1/internal_api_server/vllm/conf_api.py +147 -0
- lmcache/v1/internal_api_server/vllm/freeze_api.py +172 -0
- lmcache/v1/internal_api_server/vllm/hot_cache_api.py +184 -0
- lmcache/v1/internal_api_server/vllm/inference_api.py +65 -0
- lmcache/v1/internal_api_server/vllm/load_fs_chunks_api.py +320 -0
- lmcache/v1/internal_api_server/vllm/lookup_api.py +145 -0
- lmcache/v1/internal_api_server/vllm/version_api.py +25 -0
- lmcache/v1/kv_layer_groups.py +267 -0
- lmcache/v1/lazy_memory_allocator.py +284 -0
- lmcache/v1/lookup_client/__init__.py +25 -0
- lmcache/v1/lookup_client/abstract_client.py +77 -0
- lmcache/v1/lookup_client/async_lookup_message.py +50 -0
- lmcache/v1/lookup_client/chunk_statistics_lookup_client.py +200 -0
- lmcache/v1/lookup_client/factory.py +251 -0
- lmcache/v1/lookup_client/hit_limit_lookup_client.py +86 -0
- lmcache/v1/lookup_client/lmcache_async_lookup_client.py +407 -0
- lmcache/v1/lookup_client/lmcache_lookup_client.py +285 -0
- lmcache/v1/lookup_client/lmcache_lookup_client_bypass.py +99 -0
- lmcache/v1/lookup_client/mooncake_lookup_client.py +87 -0
- lmcache/v1/lookup_client/record_strategies/__init__.py +77 -0
- lmcache/v1/lookup_client/record_strategies/base.py +327 -0
- lmcache/v1/lookup_client/record_strategies/file_hash.py +130 -0
- lmcache/v1/lookup_client/record_strategies/memory_bloom_filter.py +81 -0
- lmcache/v1/manager.py +539 -0
- lmcache/v1/memory_management.py +2619 -0
- lmcache/v1/metadata.py +114 -0
- lmcache/v1/mp_observability/AGENTS.override.md +21 -0
- lmcache/v1/mp_observability/README.md +204 -0
- lmcache/v1/mp_observability/config.py +340 -0
- lmcache/v1/mp_observability/event.py +100 -0
- lmcache/v1/mp_observability/event_bus.py +313 -0
- lmcache/v1/mp_observability/otel_init.py +145 -0
- lmcache/v1/mp_observability/subscribers/__init__.py +28 -0
- lmcache/v1/mp_observability/subscribers/logging/__init__.py +19 -0
- lmcache/v1/mp_observability/subscribers/logging/l1.py +56 -0
- lmcache/v1/mp_observability/subscribers/logging/l2.py +73 -0
- lmcache/v1/mp_observability/subscribers/logging/lookup_hash.py +209 -0
- lmcache/v1/mp_observability/subscribers/logging/mp_server.py +90 -0
- lmcache/v1/mp_observability/subscribers/logging/sm.py +59 -0
- lmcache/v1/mp_observability/subscribers/metrics/__init__.py +20 -0
- lmcache/v1/mp_observability/subscribers/metrics/l0_lifecycle.py +290 -0
- lmcache/v1/mp_observability/subscribers/metrics/l1.py +55 -0
- lmcache/v1/mp_observability/subscribers/metrics/l1_lifecycle.py +166 -0
- lmcache/v1/mp_observability/subscribers/metrics/l2.py +121 -0
- lmcache/v1/mp_observability/subscribers/metrics/sm.py +69 -0
- lmcache/v1/mp_observability/subscribers/tracing/__init__.py +12 -0
- lmcache/v1/mp_observability/subscribers/tracing/mp_server.py +333 -0
- lmcache/v1/mp_observability/subscribers/tracing/span_registry.py +148 -0
- lmcache/v1/mp_observability/trace/__init__.py +50 -0
- lmcache/v1/mp_observability/trace/codecs.py +255 -0
- lmcache/v1/mp_observability/trace/decorator.py +147 -0
- lmcache/v1/mp_observability/trace/format.py +132 -0
- lmcache/v1/mp_observability/trace/lifecycle.py +83 -0
- lmcache/v1/mp_observability/trace/reader.py +167 -0
- lmcache/v1/mp_observability/trace/recorder.py +300 -0
- lmcache/v1/multiprocess/__init__.py +0 -0
- lmcache/v1/multiprocess/affinity_pool.py +102 -0
- lmcache/v1/multiprocess/blend_server_v2.py +891 -0
- lmcache/v1/multiprocess/config.py +253 -0
- lmcache/v1/multiprocess/custom_types.py +281 -0
- lmcache/v1/multiprocess/futures.py +194 -0
- lmcache/v1/multiprocess/gpu_context.py +511 -0
- lmcache/v1/multiprocess/http_server.py +235 -0
- lmcache/v1/multiprocess/mp_runtime_plugin_launcher.py +130 -0
- lmcache/v1/multiprocess/mq.py +732 -0
- lmcache/v1/multiprocess/protocol.py +86 -0
- lmcache/v1/multiprocess/protocols/README.md +213 -0
- lmcache/v1/multiprocess/protocols/__init__.py +127 -0
- lmcache/v1/multiprocess/protocols/base.py +89 -0
- lmcache/v1/multiprocess/protocols/blend.py +109 -0
- lmcache/v1/multiprocess/protocols/blend_v2.py +57 -0
- lmcache/v1/multiprocess/protocols/controller.py +53 -0
- lmcache/v1/multiprocess/protocols/debug.py +34 -0
- lmcache/v1/multiprocess/protocols/engine.py +146 -0
- lmcache/v1/multiprocess/protocols/observability.py +39 -0
- lmcache/v1/multiprocess/server.py +1134 -0
- lmcache/v1/multiprocess/session.py +190 -0
- lmcache/v1/multiprocess/token_hasher.py +441 -0
- lmcache/v1/offload_server/__init__.py +17 -0
- lmcache/v1/offload_server/abstract_server.py +37 -0
- lmcache/v1/offload_server/message.py +30 -0
- lmcache/v1/offload_server/zmq_server.py +122 -0
- lmcache/v1/periodic_thread.py +579 -0
- lmcache/v1/pin_monitor.py +246 -0
- lmcache/v1/plugin/__init__.py +0 -0
- lmcache/v1/plugin/runtime_plugin_launcher.py +211 -0
- lmcache/v1/protocol.py +317 -0
- lmcache/v1/rpc/__init__.py +17 -0
- lmcache/v1/rpc/transport.py +105 -0
- lmcache/v1/rpc/zmq_transport.py +213 -0
- lmcache/v1/rpc_utils.py +165 -0
- lmcache/v1/server/__init__.py +2 -0
- lmcache/v1/server/__main__.py +170 -0
- lmcache/v1/server/storage_backend/__init__.py +21 -0
- lmcache/v1/server/storage_backend/abstract_backend.py +80 -0
- lmcache/v1/server/storage_backend/local_backend.py +75 -0
- lmcache/v1/server/utils.py +21 -0
- lmcache/v1/standalone/__init__.py +1 -0
- lmcache/v1/standalone/__main__.py +583 -0
- lmcache/v1/standalone/manager.py +80 -0
- lmcache/v1/standalone/standalone_service_factory.py +86 -0
- lmcache/v1/storage_backend/__init__.py +313 -0
- lmcache/v1/storage_backend/abstract_backend.py +445 -0
- lmcache/v1/storage_backend/audit_backend.py +233 -0
- lmcache/v1/storage_backend/batched_message_sender.py +222 -0
- lmcache/v1/storage_backend/cache_policy/__init__.py +45 -0
- lmcache/v1/storage_backend/cache_policy/base_policy.py +87 -0
- lmcache/v1/storage_backend/cache_policy/fifo.py +58 -0
- lmcache/v1/storage_backend/cache_policy/lfu.py +105 -0
- lmcache/v1/storage_backend/cache_policy/lru.py +81 -0
- lmcache/v1/storage_backend/cache_policy/mru.py +61 -0
- lmcache/v1/storage_backend/connector/__init__.py +443 -0
- lmcache/v1/storage_backend/connector/audit_adapter.py +77 -0
- lmcache/v1/storage_backend/connector/audit_connector.py +320 -0
- lmcache/v1/storage_backend/connector/base_connector.py +379 -0
- lmcache/v1/storage_backend/connector/blackhole_adapter.py +21 -0
- lmcache/v1/storage_backend/connector/blackhole_connector.py +37 -0
- lmcache/v1/storage_backend/connector/eic_adapter.py +31 -0
- lmcache/v1/storage_backend/connector/eic_connector.py +757 -0
- lmcache/v1/storage_backend/connector/external_adapter.py +79 -0
- lmcache/v1/storage_backend/connector/fs_adapter.py +51 -0
- lmcache/v1/storage_backend/connector/fs_connector.py +403 -0
- lmcache/v1/storage_backend/connector/infinistore_adapter.py +56 -0
- lmcache/v1/storage_backend/connector/infinistore_connector.py +177 -0
- lmcache/v1/storage_backend/connector/instrumented_connector.py +219 -0
- lmcache/v1/storage_backend/connector/lm_adapter.py +31 -0
- lmcache/v1/storage_backend/connector/lm_connector.py +176 -0
- lmcache/v1/storage_backend/connector/mock_adapter.py +57 -0
- lmcache/v1/storage_backend/connector/mock_connector.py +349 -0
- lmcache/v1/storage_backend/connector/mooncakestore_adapter.py +43 -0
- lmcache/v1/storage_backend/connector/mooncakestore_connector.py +614 -0
- lmcache/v1/storage_backend/connector/redis_adapter.py +181 -0
- lmcache/v1/storage_backend/connector/redis_connector.py +828 -0
- lmcache/v1/storage_backend/connector/s3_adapter.py +59 -0
- lmcache/v1/storage_backend/connector/s3_connector.py +699 -0
- lmcache/v1/storage_backend/connector/sagemaker_hyperpod_adapter.py +233 -0
- lmcache/v1/storage_backend/connector/sagemaker_hyperpod_connector.py +987 -0
- lmcache/v1/storage_backend/connector/valkey_adapter.py +114 -0
- lmcache/v1/storage_backend/connector/valkey_connector.py +627 -0
- lmcache/v1/storage_backend/gds_backend.py +1199 -0
- lmcache/v1/storage_backend/job_executor/__init__.py +0 -0
- lmcache/v1/storage_backend/job_executor/base_executor.py +34 -0
- lmcache/v1/storage_backend/job_executor/pq_executor.py +235 -0
- lmcache/v1/storage_backend/local_cpu_backend.py +810 -0
- lmcache/v1/storage_backend/local_disk_backend.py +656 -0
- lmcache/v1/storage_backend/maru_backend.py +734 -0
- lmcache/v1/storage_backend/naive_serde/__init__.py +50 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_basics.py +133 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_decoder.py +135 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_encoder.py +83 -0
- lmcache/v1/storage_backend/naive_serde/kivi_serde.py +22 -0
- lmcache/v1/storage_backend/naive_serde/naive_serde.py +18 -0
- lmcache/v1/storage_backend/naive_serde/serde.py +37 -0
- lmcache/v1/storage_backend/native_clients/connector_client_base.py +165 -0
- lmcache/v1/storage_backend/native_clients/resp_client.py +35 -0
- lmcache/v1/storage_backend/nixl_storage_backend.py +1400 -0
- lmcache/v1/storage_backend/p2p_backend.py +788 -0
- lmcache/v1/storage_backend/path_sharder.py +117 -0
- lmcache/v1/storage_backend/pd_backend.py +646 -0
- lmcache/v1/storage_backend/plugins/dax_backend.py +1443 -0
- lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py +1361 -0
- lmcache/v1/storage_backend/remote_backend.py +624 -0
- lmcache/v1/storage_backend/resp_client.py +227 -0
- lmcache/v1/storage_backend/storage_backend_listener.py +19 -0
- lmcache/v1/storage_backend/storage_manager.py +1352 -0
- lmcache/v1/system_detection.py +110 -0
- lmcache/v1/token_database.py +551 -0
- lmcache/v1/transfer_channel/__init__.py +83 -0
- lmcache/v1/transfer_channel/abstract.py +285 -0
- lmcache/v1/transfer_channel/mock_memory_channel.py +156 -0
- lmcache/v1/transfer_channel/nixl_channel.py +639 -0
- lmcache/v1/transfer_channel/py_socket_channel.py +260 -0
- lmcache/v1/transfer_channel/transfer_utils.py +63 -0
- lmcache/v1/utils/__init__.py +1 -0
- lmcache/v1/utils/bloom_filter.py +109 -0
- lmcache/v1/utils/cache_utils.py +125 -0
- lmcache_cli-0.4.5.dev0.dist-info/METADATA +185 -0
- lmcache_cli-0.4.5.dev0.dist-info/RECORD +399 -0
- lmcache_cli-0.4.5.dev0.dist-info/WHEEL +5 -0
- lmcache_cli-0.4.5.dev0.dist-info/entry_points.txt +2 -0
- lmcache_cli-0.4.5.dev0.dist-info/licenses/LICENSE +201 -0
- lmcache_cli-0.4.5.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
Plugin L2 adapter -- dynamically loads an external adapter
|
|
4
|
+
class from a user-supplied Python module.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
# Future
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
# Standard
|
|
11
|
+
from typing import TYPE_CHECKING, Any, Optional
|
|
12
|
+
import importlib
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
# First Party
|
|
16
|
+
from lmcache.v1.distributed.internal_api import (
|
|
17
|
+
L1MemoryDesc,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
# First Party
|
|
21
|
+
from lmcache.v1.distributed.l2_adapters.base import L2AdapterInterface as _L2AI
|
|
22
|
+
from lmcache.v1.distributed.l2_adapters.config import (
|
|
23
|
+
L2AdapterConfigBase,
|
|
24
|
+
register_l2_adapter_type,
|
|
25
|
+
)
|
|
26
|
+
from lmcache.v1.distributed.l2_adapters.factory import (
|
|
27
|
+
register_l2_adapter_factory,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Config class
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class PluginL2AdapterConfig(L2AdapterConfigBase):
|
|
34
|
+
"""
|
|
35
|
+
Config for a plugin L2 adapter.
|
|
36
|
+
|
|
37
|
+
Dynamically loads an adapter class from a user-supplied
|
|
38
|
+
Python module at creation time.
|
|
39
|
+
|
|
40
|
+
Fields:
|
|
41
|
+
- module_path: Dotted Python import path of the module
|
|
42
|
+
containing the adapter class.
|
|
43
|
+
- class_name: Name of the class inside *module_path*
|
|
44
|
+
that implements ``L2AdapterInterface``.
|
|
45
|
+
- adapter_params: Arbitrary dict forwarded to the
|
|
46
|
+
adapter class constructor.
|
|
47
|
+
- config_class_name: Optional name of a config class
|
|
48
|
+
inside *module_path* that subclasses
|
|
49
|
+
``L2AdapterConfigBase``. When set, the factory
|
|
50
|
+
builds a config instance via ``from_dict()`` and
|
|
51
|
+
passes it (instead of a raw dict) to the adapter
|
|
52
|
+
constructor -- matching the built-in convention.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
module_path: str,
|
|
58
|
+
class_name: str,
|
|
59
|
+
adapter_params: dict[str, Any] | None = None,
|
|
60
|
+
config_class_name: str | None = None,
|
|
61
|
+
):
|
|
62
|
+
self.module_path = module_path
|
|
63
|
+
self.class_name = class_name
|
|
64
|
+
self.adapter_params = adapter_params or {}
|
|
65
|
+
self.config_class_name = config_class_name
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def from_dict(cls, d: dict) -> "PluginL2AdapterConfig":
|
|
69
|
+
module_path = d.get("module_path")
|
|
70
|
+
if not isinstance(module_path, str) or not module_path:
|
|
71
|
+
raise ValueError("module_path must be a non-empty string")
|
|
72
|
+
|
|
73
|
+
class_name = d.get("class_name")
|
|
74
|
+
if not isinstance(class_name, str) or not class_name:
|
|
75
|
+
raise ValueError("class_name must be a non-empty string")
|
|
76
|
+
|
|
77
|
+
adapter_params = d.get("adapter_params", {})
|
|
78
|
+
if not isinstance(adapter_params, dict):
|
|
79
|
+
raise ValueError("adapter_params must be a dict")
|
|
80
|
+
|
|
81
|
+
config_class_name = d.get("config_class_name")
|
|
82
|
+
if config_class_name is not None and not isinstance(config_class_name, str):
|
|
83
|
+
raise ValueError("config_class_name must be a string")
|
|
84
|
+
|
|
85
|
+
return cls(
|
|
86
|
+
module_path=module_path,
|
|
87
|
+
class_name=class_name,
|
|
88
|
+
adapter_params=adapter_params,
|
|
89
|
+
config_class_name=config_class_name,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def help(cls) -> str:
|
|
94
|
+
return (
|
|
95
|
+
"Plugin L2 adapter config fields:\n"
|
|
96
|
+
"- module_path (str): dotted import path of "
|
|
97
|
+
"the module containing the adapter class "
|
|
98
|
+
"(required)\n"
|
|
99
|
+
"- class_name (str): name of the adapter "
|
|
100
|
+
"class inside the module (required)\n"
|
|
101
|
+
"- adapter_params (dict): forwarded to the "
|
|
102
|
+
"adapter constructor "
|
|
103
|
+
"(optional, default {})\n"
|
|
104
|
+
"- config_class_name (str): explicit config "
|
|
105
|
+
"class name; when omitted the factory "
|
|
106
|
+
"auto-discovers it (see plugin.md)\n"
|
|
107
|
+
"\n"
|
|
108
|
+
"Example JSON (raw dict):\n"
|
|
109
|
+
'{"type": "plugin", '
|
|
110
|
+
'"module_path": "my_plugin.l2", '
|
|
111
|
+
'"class_name": "MyL2Adapter", '
|
|
112
|
+
'"adapter_params": {"host": "localhost"}}\n'
|
|
113
|
+
"\n"
|
|
114
|
+
"Example JSON (with config class):\n"
|
|
115
|
+
'{"type": "plugin", '
|
|
116
|
+
'"module_path": "my_plugin.l2", '
|
|
117
|
+
'"class_name": "MyL2Adapter", '
|
|
118
|
+
'"config_class_name": "MyL2AdapterConfig", '
|
|
119
|
+
'"adapter_params": {"host": "localhost"}}'
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# Factory function
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def _create_plugin_adapter(
|
|
127
|
+
config: L2AdapterConfigBase,
|
|
128
|
+
l1_memory_desc: "Optional[L1MemoryDesc]" = None,
|
|
129
|
+
) -> _L2AI:
|
|
130
|
+
"""Dynamically load and create a plugin L2 adapter."""
|
|
131
|
+
assert isinstance(config, PluginL2AdapterConfig)
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
module = importlib.import_module(config.module_path)
|
|
135
|
+
except ImportError as e:
|
|
136
|
+
raise ImportError(
|
|
137
|
+
"Could not import module '%s': %s" % (config.module_path, e)
|
|
138
|
+
) from e
|
|
139
|
+
|
|
140
|
+
try:
|
|
141
|
+
adapter_cls = getattr(module, config.class_name)
|
|
142
|
+
except AttributeError as e:
|
|
143
|
+
raise AttributeError(
|
|
144
|
+
"Module '%s' has no class '%s': %s"
|
|
145
|
+
% (config.module_path, config.class_name, e)
|
|
146
|
+
) from e
|
|
147
|
+
|
|
148
|
+
if not (isinstance(adapter_cls, type) and issubclass(adapter_cls, _L2AI)):
|
|
149
|
+
raise TypeError(
|
|
150
|
+
"%s.%s is not a subclass of "
|
|
151
|
+
"L2AdapterInterface" % (config.module_path, config.class_name)
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
cfg_cls = _resolve_config_class(
|
|
155
|
+
module,
|
|
156
|
+
config,
|
|
157
|
+
adapter_cls,
|
|
158
|
+
)
|
|
159
|
+
kwargs: dict[str, object] = {}
|
|
160
|
+
if l1_memory_desc is not None:
|
|
161
|
+
kwargs["l1_memory_desc"] = l1_memory_desc
|
|
162
|
+
|
|
163
|
+
if cfg_cls is not None:
|
|
164
|
+
return adapter_cls( # type: ignore[call-arg]
|
|
165
|
+
cfg_cls.from_dict(config.adapter_params),
|
|
166
|
+
**kwargs,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
return adapter_cls( # type: ignore[call-arg]
|
|
170
|
+
config.adapter_params,
|
|
171
|
+
**kwargs,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def _resolve_config_class(
|
|
176
|
+
module: object,
|
|
177
|
+
config: PluginL2AdapterConfig,
|
|
178
|
+
adapter_cls: type,
|
|
179
|
+
) -> type[L2AdapterConfigBase] | None:
|
|
180
|
+
"""Resolve the config class for a plugin adapter.
|
|
181
|
+
|
|
182
|
+
Discovery order:
|
|
183
|
+
1. Explicit ``config.config_class_name`` field.
|
|
184
|
+
2. Convention: ``config.class_name`` + ``"Config"``.
|
|
185
|
+
3. ``config_class_name`` attribute on the adapter
|
|
186
|
+
class itself.
|
|
187
|
+
4. ``None`` -- fall back to raw dict mode.
|
|
188
|
+
"""
|
|
189
|
+
candidates: list[str | None] = [
|
|
190
|
+
config.config_class_name,
|
|
191
|
+
config.class_name + "Config",
|
|
192
|
+
getattr(adapter_cls, "config_class_name", None),
|
|
193
|
+
]
|
|
194
|
+
for name in candidates:
|
|
195
|
+
if not name:
|
|
196
|
+
continue
|
|
197
|
+
cls = getattr(module, name, None)
|
|
198
|
+
if cls is None:
|
|
199
|
+
continue
|
|
200
|
+
if isinstance(cls, type) and issubclass(
|
|
201
|
+
cls,
|
|
202
|
+
L2AdapterConfigBase,
|
|
203
|
+
):
|
|
204
|
+
return cls
|
|
205
|
+
return None
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
# Self-register config type and adapter factory
|
|
209
|
+
register_l2_adapter_type("plugin", PluginL2AdapterConfig)
|
|
210
|
+
register_l2_adapter_factory("plugin", _create_plugin_adapter)
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
RESP (Redis/Valkey) L2 adapter config and factory.
|
|
4
|
+
|
|
5
|
+
Backed by the native C++ Redis connector wrapped with
|
|
6
|
+
``NativeConnectorL2Adapter``.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# Future
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
# Standard
|
|
13
|
+
from typing import TYPE_CHECKING, Optional
|
|
14
|
+
import os
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from lmcache.v1.distributed.internal_api import (
|
|
18
|
+
L1MemoryDesc,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# First Party
|
|
22
|
+
from lmcache.logging import init_logger
|
|
23
|
+
from lmcache.v1.distributed.l2_adapters.base import (
|
|
24
|
+
L2AdapterInterface,
|
|
25
|
+
)
|
|
26
|
+
from lmcache.v1.distributed.l2_adapters.config import (
|
|
27
|
+
L2AdapterConfigBase,
|
|
28
|
+
register_l2_adapter_type,
|
|
29
|
+
)
|
|
30
|
+
from lmcache.v1.distributed.l2_adapters.factory import (
|
|
31
|
+
register_l2_adapter_factory,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
logger = init_logger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class RESPL2AdapterConfig(L2AdapterConfigBase):
|
|
38
|
+
"""
|
|
39
|
+
Config for an L2 adapter backed by a native RESP
|
|
40
|
+
connector (Redis/Valkey).
|
|
41
|
+
|
|
42
|
+
Fields:
|
|
43
|
+
- host: server hostname or IP.
|
|
44
|
+
- port: server port.
|
|
45
|
+
- num_workers: C++ worker threads for I/O (default 8).
|
|
46
|
+
- username: optional auth username.
|
|
47
|
+
- password: optional auth password.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(
|
|
51
|
+
self,
|
|
52
|
+
host: str,
|
|
53
|
+
port: int,
|
|
54
|
+
num_workers: int = 8,
|
|
55
|
+
username: str = "",
|
|
56
|
+
password: str = "",
|
|
57
|
+
max_capacity_gb: float = 0,
|
|
58
|
+
):
|
|
59
|
+
super().__init__()
|
|
60
|
+
self.host = host
|
|
61
|
+
self.port = port
|
|
62
|
+
self.num_workers = num_workers
|
|
63
|
+
self.username = username
|
|
64
|
+
self.password = password
|
|
65
|
+
self.max_capacity_gb = max_capacity_gb
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def from_dict(cls, d: dict) -> "RESPL2AdapterConfig":
|
|
69
|
+
host = d.get("host")
|
|
70
|
+
if not isinstance(host, str) or not host:
|
|
71
|
+
raise ValueError("host must be a non-empty string")
|
|
72
|
+
|
|
73
|
+
port = d.get("port")
|
|
74
|
+
if not isinstance(port, int) or port <= 0:
|
|
75
|
+
raise ValueError("port must be a positive integer")
|
|
76
|
+
|
|
77
|
+
num_workers = d.get("num_workers", 8)
|
|
78
|
+
if not isinstance(num_workers, int) or num_workers <= 0:
|
|
79
|
+
raise ValueError("num_workers must be a positive integer")
|
|
80
|
+
|
|
81
|
+
username = d.get("username", "")
|
|
82
|
+
password = d.get("password", "")
|
|
83
|
+
|
|
84
|
+
max_capacity_gb = d.get("max_capacity_gb", 0)
|
|
85
|
+
if not isinstance(max_capacity_gb, (int, float)) or max_capacity_gb < 0:
|
|
86
|
+
raise ValueError("max_capacity_gb must be a non-negative number")
|
|
87
|
+
|
|
88
|
+
return cls(
|
|
89
|
+
host=host,
|
|
90
|
+
port=port,
|
|
91
|
+
num_workers=num_workers,
|
|
92
|
+
username=str(username),
|
|
93
|
+
password=str(password),
|
|
94
|
+
max_capacity_gb=float(max_capacity_gb),
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
@classmethod
|
|
98
|
+
def help(cls) -> str:
|
|
99
|
+
return (
|
|
100
|
+
"RESP L2 adapter config fields:\n"
|
|
101
|
+
"- host (str): Redis/Valkey server hostname "
|
|
102
|
+
"or IP (required)\n"
|
|
103
|
+
"- port (int): server port (required, >0)\n"
|
|
104
|
+
"- num_workers (int): C++ worker threads "
|
|
105
|
+
"for I/O (default 8, >0)\n"
|
|
106
|
+
"- username (str): auth username "
|
|
107
|
+
"(default empty)\n"
|
|
108
|
+
"- password (str): auth password "
|
|
109
|
+
"(default empty)\n"
|
|
110
|
+
"- max_capacity_gb (float): max L2 capacity "
|
|
111
|
+
"in GB for usage tracking / eviction "
|
|
112
|
+
"(default 0 = disabled)\n\n"
|
|
113
|
+
"Environment variable defaults (used when "
|
|
114
|
+
"config value is empty, read at adapter "
|
|
115
|
+
"creation, not stored in config):\n"
|
|
116
|
+
"- LMCACHE_RESP_USERNAME: default username\n"
|
|
117
|
+
"- LMCACHE_RESP_PASSWORD: default password\n"
|
|
118
|
+
"- LMCACHE_RESP_HOST: default host\n"
|
|
119
|
+
"- LMCACHE_RESP_PORT: default port"
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def _create_resp_l2_adapter(
|
|
124
|
+
config: L2AdapterConfigBase,
|
|
125
|
+
l1_memory_desc: "Optional[L1MemoryDesc]" = None,
|
|
126
|
+
) -> L2AdapterInterface:
|
|
127
|
+
"""Create a NativeConnectorL2Adapter backed by the
|
|
128
|
+
C++ Redis connector."""
|
|
129
|
+
try:
|
|
130
|
+
# First Party
|
|
131
|
+
from lmcache.lmcache_redis import (
|
|
132
|
+
LMCacheRedisClient,
|
|
133
|
+
)
|
|
134
|
+
except ImportError as e:
|
|
135
|
+
raise RuntimeError(
|
|
136
|
+
"RESP L2 adapter requires the C++ Redis "
|
|
137
|
+
"extension. Build with: pip install -e ."
|
|
138
|
+
) from e
|
|
139
|
+
|
|
140
|
+
# Lazy import to avoid circular dependency
|
|
141
|
+
# First Party
|
|
142
|
+
from lmcache.v1.distributed.l2_adapters.native_connector_l2_adapter import ( # noqa: E501
|
|
143
|
+
NativeConnectorL2Adapter,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
assert isinstance(config, RESPL2AdapterConfig)
|
|
147
|
+
|
|
148
|
+
# Config/CLI args take precedence over environment variables,
|
|
149
|
+
# which serve as defaults. This keeps secrets out of logged
|
|
150
|
+
# config while allowing explicit CLI overrides.
|
|
151
|
+
host = config.host or os.environ.get("LMCACHE_RESP_HOST", "")
|
|
152
|
+
port = config.port if config.port else int(os.environ.get("LMCACHE_RESP_PORT", "0"))
|
|
153
|
+
username = config.username or os.environ.get("LMCACHE_RESP_USERNAME", "")
|
|
154
|
+
password = config.password or os.environ.get("LMCACHE_RESP_PASSWORD", "")
|
|
155
|
+
|
|
156
|
+
native_client = LMCacheRedisClient(
|
|
157
|
+
host,
|
|
158
|
+
port,
|
|
159
|
+
config.num_workers,
|
|
160
|
+
username,
|
|
161
|
+
password,
|
|
162
|
+
)
|
|
163
|
+
logger.info(
|
|
164
|
+
"Created RESP L2 adapter: %s:%d (workers=%d)",
|
|
165
|
+
host,
|
|
166
|
+
port,
|
|
167
|
+
config.num_workers,
|
|
168
|
+
)
|
|
169
|
+
return NativeConnectorL2Adapter(
|
|
170
|
+
native_client, max_capacity_gb=config.max_capacity_gb
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# Self-register config type and adapter factory
|
|
175
|
+
register_l2_adapter_type("resp", RESPL2AdapterConfig)
|
|
176
|
+
register_l2_adapter_factory("resp", _create_resp_l2_adapter)
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
|
|
3
|
+
# First Party
|
|
4
|
+
from lmcache.logging import init_logger
|
|
5
|
+
from lmcache.v1.distributed.api import MemoryLayoutDesc
|
|
6
|
+
from lmcache.v1.distributed.config import L1MemoryManagerConfig
|
|
7
|
+
from lmcache.v1.distributed.error import L1Error
|
|
8
|
+
from lmcache.v1.distributed.internal_api import L1MemoryDesc
|
|
9
|
+
from lmcache.v1.lazy_memory_allocator import LazyMemoryAllocator
|
|
10
|
+
from lmcache.v1.memory_management import (
|
|
11
|
+
MemoryAllocatorInterface,
|
|
12
|
+
MemoryObj,
|
|
13
|
+
MixedMemoryAllocator,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
logger = init_logger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# HELPER FUNCTIONS
|
|
20
|
+
def create_memory_allocator(config: L1MemoryManagerConfig) -> MemoryAllocatorInterface:
|
|
21
|
+
"""
|
|
22
|
+
Create a memory allocator based on the provided configuration.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
config (L1MemoryManagerConfig): Configuration for the memory manager.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
MemoryAllocatorInterface: An instance of a memory allocator.
|
|
29
|
+
"""
|
|
30
|
+
if config.use_lazy:
|
|
31
|
+
logger.debug(
|
|
32
|
+
"use lazy memory allocator, init size is %d bytes, "
|
|
33
|
+
"final size is %d bytes, align bytes is %d bytes",
|
|
34
|
+
config.init_size_in_bytes,
|
|
35
|
+
config.size_in_bytes,
|
|
36
|
+
config.align_bytes,
|
|
37
|
+
)
|
|
38
|
+
return LazyMemoryAllocator(
|
|
39
|
+
config.init_size_in_bytes, config.size_in_bytes, config.align_bytes
|
|
40
|
+
)
|
|
41
|
+
else:
|
|
42
|
+
logger.debug(
|
|
43
|
+
"use mixed memory allocator, total size is %d bytes, "
|
|
44
|
+
"align bytes is %d bytes",
|
|
45
|
+
config.size_in_bytes,
|
|
46
|
+
config.align_bytes,
|
|
47
|
+
)
|
|
48
|
+
return MixedMemoryAllocator(
|
|
49
|
+
config.size_in_bytes,
|
|
50
|
+
align_bytes=config.align_bytes,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# MAIN CLASS
|
|
55
|
+
class L1MemoryManager:
|
|
56
|
+
"""
|
|
57
|
+
L1MemoryManager manages the allocation and deallocation of L1 memory.
|
|
58
|
+
|
|
59
|
+
Observability metrics to emit:
|
|
60
|
+
1. Memory usage
|
|
61
|
+
2. Active allocations
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
def __init__(self, config: L1MemoryManagerConfig):
|
|
65
|
+
self._allocator = create_memory_allocator(config)
|
|
66
|
+
self._size_in_bytes = config.size_in_bytes
|
|
67
|
+
self._align_bytes = config.align_bytes
|
|
68
|
+
|
|
69
|
+
def allocate(
|
|
70
|
+
self, layout_desc: MemoryLayoutDesc, count: int
|
|
71
|
+
) -> tuple[L1Error, list[MemoryObj]]:
|
|
72
|
+
"""
|
|
73
|
+
Allocate memory objects based on the provided layout description and count.
|
|
74
|
+
This function should be thread-safe
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
layout_desc (MemoryLayoutDesc): Description of the memory layout.
|
|
78
|
+
count (int): Number of memory objects to allocate.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
tuple[L1Error, list[MemoryObj]]: Error code and list of
|
|
82
|
+
allocated memory objects.
|
|
83
|
+
Error code will be `L1Error.OUT_OF_MEMORY` if allocation
|
|
84
|
+
fails; otherwise, it will be `L1Error.SUCCESS`.
|
|
85
|
+
|
|
86
|
+
Note:
|
|
87
|
+
If the allocation fails, the memory object list will be empty.
|
|
88
|
+
"""
|
|
89
|
+
objects = self._allocator.batched_allocate(
|
|
90
|
+
layout_desc.shapes, layout_desc.dtypes, count
|
|
91
|
+
)
|
|
92
|
+
if objects is None:
|
|
93
|
+
return L1Error.OUT_OF_MEMORY, []
|
|
94
|
+
return L1Error.SUCCESS, objects
|
|
95
|
+
|
|
96
|
+
def free(self, mem_objs: list[MemoryObj]) -> L1Error:
|
|
97
|
+
"""
|
|
98
|
+
Free the provided memory objects.
|
|
99
|
+
This function should be thread-safe.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
mem_objs (list[MemoryObj]): List of memory objects to free.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
L1Error: Error code indicating the result of the operation.
|
|
106
|
+
It will be `L1Error.SUCCESS` if the operation succeeds.
|
|
107
|
+
"""
|
|
108
|
+
self._allocator.batched_free(mem_objs)
|
|
109
|
+
return L1Error.SUCCESS
|
|
110
|
+
|
|
111
|
+
def get_memory_usage(self) -> tuple[int, int]:
|
|
112
|
+
"""
|
|
113
|
+
Get the current memory usage. This function will mainly be used to support
|
|
114
|
+
eviction decision.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
tuple[int, int]: A tuple containing used memory in bytes and total memory
|
|
118
|
+
in bytes.
|
|
119
|
+
|
|
120
|
+
Note:
|
|
121
|
+
In the future, we may want to make a "callback" based mechanism to
|
|
122
|
+
trigger eviction when the memory usage reaches a watermark.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
# HACK: now trying to read this from the address manager in a ad-hoc
|
|
126
|
+
# manner
|
|
127
|
+
def get_address_manager(allocator: MemoryAllocatorInterface):
|
|
128
|
+
if isinstance(allocator, MixedMemoryAllocator) and hasattr(
|
|
129
|
+
allocator.pin_allocator, "address_manager"
|
|
130
|
+
):
|
|
131
|
+
return allocator.pin_allocator.address_manager
|
|
132
|
+
elif isinstance(allocator, LazyMemoryAllocator):
|
|
133
|
+
return allocator.get_address_manager()
|
|
134
|
+
else:
|
|
135
|
+
raise NotImplementedError(
|
|
136
|
+
"get_memory_usage is not implemented for this allocator type."
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
address_manager = get_address_manager(self._allocator)
|
|
140
|
+
free_size = address_manager.get_free_size()
|
|
141
|
+
total_size = address_manager.get_heap_size()
|
|
142
|
+
used_size = total_size - free_size
|
|
143
|
+
return used_size, total_size
|
|
144
|
+
|
|
145
|
+
def get_l1_memory_desc(self) -> L1MemoryDesc:
|
|
146
|
+
"""
|
|
147
|
+
Return an L1MemoryDesc describing the underlying memory buffer.
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
L1MemoryDesc: Pointer, size, and alignment of the L1 buffer.
|
|
151
|
+
|
|
152
|
+
Raises:
|
|
153
|
+
NotImplementedError: If the allocator type does not support this operation.
|
|
154
|
+
"""
|
|
155
|
+
if isinstance(self._allocator, MixedMemoryAllocator):
|
|
156
|
+
buffer = self._allocator.buffer
|
|
157
|
+
elif isinstance(self._allocator, LazyMemoryAllocator):
|
|
158
|
+
# TODO(ApostaC): need to test if the RDMA registration works
|
|
159
|
+
# before the lazy expansion is finished
|
|
160
|
+
buffer = self._allocator.get_underlying_buffer()
|
|
161
|
+
else:
|
|
162
|
+
raise NotImplementedError(
|
|
163
|
+
"get_l1_memory_desc is not implemented for this allocator type."
|
|
164
|
+
)
|
|
165
|
+
return L1MemoryDesc(
|
|
166
|
+
ptr=buffer.data_ptr(),
|
|
167
|
+
size=self._size_in_bytes,
|
|
168
|
+
align_bytes=self._align_bytes,
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def close(self) -> None:
|
|
172
|
+
"""
|
|
173
|
+
Close the memory manager and release all resources.
|
|
174
|
+
"""
|
|
175
|
+
self._allocator.close()
|
|
176
|
+
|
|
177
|
+
# Debugging APIs
|
|
178
|
+
def memcheck(self):
|
|
179
|
+
return self._allocator.memcheck()
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
Interface for storage controllers
|
|
4
|
+
|
|
5
|
+
Storage controllers are separate modules/threads that sees the L1 Manager
|
|
6
|
+
and can operate on it.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
# Standard
|
|
10
|
+
from abc import ABC, abstractmethod
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class StorageControllerInterface(ABC):
|
|
14
|
+
@abstractmethod
|
|
15
|
+
def start(self):
|
|
16
|
+
"""
|
|
17
|
+
Start the storage controller.
|
|
18
|
+
This function should be implemented by subclasses to start
|
|
19
|
+
any necessary threads or processes.
|
|
20
|
+
"""
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def stop(self):
|
|
25
|
+
"""
|
|
26
|
+
Stop the storage controller.
|
|
27
|
+
This function should be implemented by subclasses to stop
|
|
28
|
+
any running threads or processes.
|
|
29
|
+
"""
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
@abstractmethod
|
|
33
|
+
def report_status(self) -> dict:
|
|
34
|
+
"""
|
|
35
|
+
Return a status dict for this controller.
|
|
36
|
+
|
|
37
|
+
Must include at least ``is_healthy: bool``.
|
|
38
|
+
"""
|
|
39
|
+
pass
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""
|
|
3
|
+
Storage controllers with automatic module discovery.
|
|
4
|
+
|
|
5
|
+
All modules under this package that call ``register_store_policy`` or
|
|
6
|
+
``register_prefetch_policy`` at import time are discovered automatically.
|
|
7
|
+
To add a new policy, simply create a new module in this directory -- **no
|
|
8
|
+
changes to any existing file are needed**.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# Standard
|
|
12
|
+
import importlib
|
|
13
|
+
import pkgutil
|
|
14
|
+
|
|
15
|
+
# First Party
|
|
16
|
+
from lmcache.v1.distributed.storage_controllers.eviction_controller import (
|
|
17
|
+
EvictionController,
|
|
18
|
+
L1EvictionController,
|
|
19
|
+
L2AdapterEvictionState,
|
|
20
|
+
L2EvictionController,
|
|
21
|
+
)
|
|
22
|
+
from lmcache.v1.distributed.storage_controllers.prefetch_controller import (
|
|
23
|
+
PrefetchController,
|
|
24
|
+
)
|
|
25
|
+
from lmcache.v1.distributed.storage_controllers.store_controller import (
|
|
26
|
+
StoreController,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
# Auto-discover and import every module in this package so
|
|
30
|
+
# that each policy's self-registration code runs.
|
|
31
|
+
_PACKAGE_PATH = __path__ # type: ignore[name-defined]
|
|
32
|
+
_PACKAGE_NAME = __name__
|
|
33
|
+
for _finder, _mod_name, _is_pkg in pkgutil.iter_modules(_PACKAGE_PATH):
|
|
34
|
+
importlib.import_module(f".{_mod_name}", _PACKAGE_NAME)
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
"EvictionController",
|
|
38
|
+
"L1EvictionController",
|
|
39
|
+
"L2EvictionController",
|
|
40
|
+
"L2AdapterEvictionState",
|
|
41
|
+
"PrefetchController",
|
|
42
|
+
"StoreController",
|
|
43
|
+
]
|