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,614 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import List, Optional, no_type_check
|
|
5
|
+
import asyncio
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
# Third Party
|
|
10
|
+
import torch
|
|
11
|
+
|
|
12
|
+
# First Party
|
|
13
|
+
from lmcache.logging import init_logger
|
|
14
|
+
from lmcache.utils import CacheEngineKey
|
|
15
|
+
from lmcache.v1.config import LMCacheEngineConfig
|
|
16
|
+
from lmcache.v1.memory_management import MemoryObj
|
|
17
|
+
from lmcache.v1.protocol import RemoteMetadata
|
|
18
|
+
from lmcache.v1.storage_backend.connector.base_connector import RemoteConnector
|
|
19
|
+
from lmcache.v1.storage_backend.local_cpu_backend import LocalCPUBackend
|
|
20
|
+
from lmcache.v1.system_detection import NUMADetector
|
|
21
|
+
|
|
22
|
+
logger = init_logger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class MooncakeStoreConfig:
|
|
27
|
+
local_hostname: str
|
|
28
|
+
metadata_server: str
|
|
29
|
+
global_segment_size: int
|
|
30
|
+
local_buffer_size: int
|
|
31
|
+
protocol: str
|
|
32
|
+
device_name: str
|
|
33
|
+
master_server_address: str
|
|
34
|
+
transfer_timeout: int
|
|
35
|
+
storage_root_dir: str
|
|
36
|
+
prefer_local_alloc: bool = False
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def from_file(file_path: str) -> "MooncakeStoreConfig":
|
|
40
|
+
"""Load the config from a JSON file."""
|
|
41
|
+
with open(file_path) as fin:
|
|
42
|
+
config = json.load(fin)
|
|
43
|
+
# Read Mooncake-specific knob
|
|
44
|
+
prefer_local_alloc = config.get("mooncake_prefer_local_alloc", False)
|
|
45
|
+
|
|
46
|
+
return MooncakeStoreConfig(
|
|
47
|
+
local_hostname=config.get("local_hostname"),
|
|
48
|
+
metadata_server=config.get("metadata_server"),
|
|
49
|
+
global_segment_size=config.get("global_segment_size", 3355443200),
|
|
50
|
+
local_buffer_size=config.get("local_buffer_size", 1073741824),
|
|
51
|
+
protocol=config.get("protocol", "tcp"),
|
|
52
|
+
device_name=config.get("device_name", ""),
|
|
53
|
+
master_server_address=config.get("master_server_address"),
|
|
54
|
+
transfer_timeout=config.get("transfer_timeout", 1),
|
|
55
|
+
storage_root_dir=config.get("storage_root_dir", ""),
|
|
56
|
+
prefer_local_alloc=prefer_local_alloc,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
@staticmethod
|
|
60
|
+
def load_from_env() -> "MooncakeStoreConfig":
|
|
61
|
+
"""Load config from a file specified in the environment variable."""
|
|
62
|
+
config_file_path = os.getenv("MOONCAKE_CONFIG_PATH")
|
|
63
|
+
if config_file_path is None:
|
|
64
|
+
raise ValueError(
|
|
65
|
+
"The environment variable 'MOONCAKE_CONFIG_PATH' is not set."
|
|
66
|
+
)
|
|
67
|
+
return MooncakeStoreConfig.from_file(config_file_path)
|
|
68
|
+
|
|
69
|
+
@staticmethod
|
|
70
|
+
def load_from_lmcache_config(
|
|
71
|
+
config: "LMCacheEngineConfig",
|
|
72
|
+
) -> "MooncakeStoreConfig":
|
|
73
|
+
"""Load config from a file specified in the environment variable."""
|
|
74
|
+
extra_config = config.extra_config
|
|
75
|
+
if extra_config is None:
|
|
76
|
+
raise ValueError("The extra config is not set.")
|
|
77
|
+
# Read Mooncake-specific knob
|
|
78
|
+
prefer_local_alloc = extra_config.get("mooncake_prefer_local_alloc", False)
|
|
79
|
+
|
|
80
|
+
return MooncakeStoreConfig(
|
|
81
|
+
local_hostname=extra_config["local_hostname"],
|
|
82
|
+
metadata_server=extra_config["metadata_server"],
|
|
83
|
+
global_segment_size=extra_config.get("global_segment_size", 3355443200),
|
|
84
|
+
local_buffer_size=extra_config.get("local_buffer_size", 1073741824),
|
|
85
|
+
protocol=extra_config.get("protocol", "tcp"),
|
|
86
|
+
device_name=extra_config.get("device_name", ""),
|
|
87
|
+
master_server_address=extra_config["master_server_address"],
|
|
88
|
+
transfer_timeout=extra_config.get("transfer_timeout", 1),
|
|
89
|
+
storage_root_dir=extra_config.get("storage_root_dir", ""),
|
|
90
|
+
prefer_local_alloc=prefer_local_alloc,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class MooncakestoreConnector(RemoteConnector):
|
|
95
|
+
def __init__(
|
|
96
|
+
self,
|
|
97
|
+
loop: asyncio.AbstractEventLoop,
|
|
98
|
+
local_cpu_backend: LocalCPUBackend,
|
|
99
|
+
lmcache_config: Optional[LMCacheEngineConfig],
|
|
100
|
+
plugin_name: Optional[str] = None,
|
|
101
|
+
):
|
|
102
|
+
# initialize base class, which includes some common attributes
|
|
103
|
+
super().__init__(local_cpu_backend.config, local_cpu_backend.metadata)
|
|
104
|
+
|
|
105
|
+
try:
|
|
106
|
+
# Third Party
|
|
107
|
+
from mooncake.store import (
|
|
108
|
+
MooncakeDistributedStore,
|
|
109
|
+
ReplicateConfig,
|
|
110
|
+
)
|
|
111
|
+
except ImportError as e:
|
|
112
|
+
raise ImportError(
|
|
113
|
+
"Please install mooncake by following the instructions at "
|
|
114
|
+
"https://github.com/kvcache-ai/Mooncake/blob/main/doc/en/build.md " # noqa: E501
|
|
115
|
+
"to run vLLM with MooncakeConnector."
|
|
116
|
+
) from e
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
self.store = MooncakeDistributedStore()
|
|
120
|
+
config_file_path = os.getenv("MOONCAKE_CONFIG_PATH")
|
|
121
|
+
if config_file_path is not None:
|
|
122
|
+
self.config = MooncakeStoreConfig.from_file(config_file_path)
|
|
123
|
+
elif lmcache_config is not None:
|
|
124
|
+
self.config = MooncakeStoreConfig.load_from_lmcache_config(
|
|
125
|
+
lmcache_config
|
|
126
|
+
)
|
|
127
|
+
else:
|
|
128
|
+
raise ValueError("MOONCAKE_CONFIG_PATH/lmcache_config must be provided")
|
|
129
|
+
|
|
130
|
+
logger.info("Mooncake Configuration loaded. config: %s", self.config)
|
|
131
|
+
|
|
132
|
+
# Check if storage_root_dir exists and set environment variable
|
|
133
|
+
if (
|
|
134
|
+
self.config.storage_root_dir is not None
|
|
135
|
+
and self.config.storage_root_dir != ""
|
|
136
|
+
):
|
|
137
|
+
os.environ["MOONCAKE_STORAGE_ROOT_DIR"] = self.config.storage_root_dir
|
|
138
|
+
logger.info(
|
|
139
|
+
"Set MOONCAKE_STORAGE_ROOT_DIR to: %s", self.config.storage_root_dir
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
logger.info("Setting up Mooncake store with parameters:")
|
|
143
|
+
logger.info(f" local_hostname: {self.config.local_hostname}")
|
|
144
|
+
logger.info(f" metadata_server: {self.config.metadata_server}")
|
|
145
|
+
logger.info(f" global_segment_size: {self.config.global_segment_size}")
|
|
146
|
+
logger.info(f" local_buffer_size: {self.config.local_buffer_size}")
|
|
147
|
+
logger.info(f" protocol: {self.config.protocol}")
|
|
148
|
+
logger.info(f" device_name: {self.config.device_name}")
|
|
149
|
+
logger.info(f" master_server_address: {self.config.master_server_address}")
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
numa_mapping = getattr(
|
|
153
|
+
local_cpu_backend.memory_allocator, "numa_mapping", None
|
|
154
|
+
)
|
|
155
|
+
if numa_mapping is None and lmcache_config is not None:
|
|
156
|
+
numa_mapping = NUMADetector.get_numa_mapping(lmcache_config)
|
|
157
|
+
|
|
158
|
+
if numa_mapping:
|
|
159
|
+
current_device_id = torch.cuda.current_device()
|
|
160
|
+
gpu_to_numa = getattr(numa_mapping, "gpu_to_numa_mapping", {})
|
|
161
|
+
numa_id = gpu_to_numa.get(current_device_id)
|
|
162
|
+
logger.info(
|
|
163
|
+
f"NUMA mapping detected (pre-Mooncake setup): {gpu_to_numa}"
|
|
164
|
+
)
|
|
165
|
+
try:
|
|
166
|
+
# Third Party
|
|
167
|
+
from mooncake.store import bind_to_numa_node
|
|
168
|
+
|
|
169
|
+
if numa_id is not None:
|
|
170
|
+
bind_to_numa_node(numa_id)
|
|
171
|
+
logger.info(
|
|
172
|
+
f"GPU {current_device_id}, "
|
|
173
|
+
f"NUMA node {numa_id} binding done"
|
|
174
|
+
)
|
|
175
|
+
else:
|
|
176
|
+
logger.info(
|
|
177
|
+
f"NUMA mapping not found for GPU {current_device_id}"
|
|
178
|
+
)
|
|
179
|
+
except ImportError:
|
|
180
|
+
logger.warning(
|
|
181
|
+
"unable to import bind_to_numa_node from mooncake.store"
|
|
182
|
+
)
|
|
183
|
+
else:
|
|
184
|
+
logger.info("NUMA mapping unavailable or disabled")
|
|
185
|
+
except Exception as e:
|
|
186
|
+
logger.warning(
|
|
187
|
+
f"Failed to determine NUMA mapping before Mooncake setup: {e}"
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
self.store.setup(
|
|
191
|
+
self.config.local_hostname,
|
|
192
|
+
self.config.metadata_server,
|
|
193
|
+
self.config.global_segment_size,
|
|
194
|
+
self.config.local_buffer_size,
|
|
195
|
+
self.config.protocol,
|
|
196
|
+
self.config.device_name,
|
|
197
|
+
self.config.master_server_address,
|
|
198
|
+
)
|
|
199
|
+
logger.info("Mooncake store setup completed successfully")
|
|
200
|
+
|
|
201
|
+
except ValueError as e:
|
|
202
|
+
logger.error("Configuration loading failed: %s", e)
|
|
203
|
+
raise
|
|
204
|
+
except Exception as exc:
|
|
205
|
+
logger.error("An error occurred while loading the configuration: %s", exc)
|
|
206
|
+
raise
|
|
207
|
+
|
|
208
|
+
self.loop = loop
|
|
209
|
+
self.local_cpu_backend = local_cpu_backend
|
|
210
|
+
self.registered_buffer_ptr = None
|
|
211
|
+
|
|
212
|
+
# Initialize ReplicateConfig
|
|
213
|
+
self.replica_config = ReplicateConfig()
|
|
214
|
+
self.replica_config.replica_num = 1
|
|
215
|
+
|
|
216
|
+
# Set preferred_segment based on configuration
|
|
217
|
+
if self.config.prefer_local_alloc:
|
|
218
|
+
self.replica_config.preferred_segment = self.store.get_hostname()
|
|
219
|
+
|
|
220
|
+
# Register CPU buffer for zero-copy operations
|
|
221
|
+
self._register_cpu_buffer()
|
|
222
|
+
|
|
223
|
+
logger.info("MooncakeConnector initialized successfully.")
|
|
224
|
+
|
|
225
|
+
def _register_cpu_buffer(self):
|
|
226
|
+
"""Register CPU buffer for zero-copy operations."""
|
|
227
|
+
try:
|
|
228
|
+
allocator = self.local_cpu_backend.memory_allocator
|
|
229
|
+
if hasattr(allocator, "pin_allocator") and hasattr(
|
|
230
|
+
allocator.pin_allocator, "buffer"
|
|
231
|
+
):
|
|
232
|
+
buffer = allocator.pin_allocator.buffer
|
|
233
|
+
self.registered_buffer_ptr = buffer.data_ptr()
|
|
234
|
+
result = self.store.register_buffer(buffer.data_ptr(), buffer.numel())
|
|
235
|
+
if result == 0:
|
|
236
|
+
logger.info(
|
|
237
|
+
f"Registered: {hex(buffer.data_ptr())}, {buffer.numel()} bytes"
|
|
238
|
+
)
|
|
239
|
+
else:
|
|
240
|
+
logger.warning(f"Buffer registration failed: error={result}")
|
|
241
|
+
self.registered_buffer_ptr = None
|
|
242
|
+
else:
|
|
243
|
+
self.registered_buffer_ptr = None
|
|
244
|
+
except Exception as e:
|
|
245
|
+
logger.error(f"Buffer registration error: {e}")
|
|
246
|
+
self.registered_buffer_ptr = None
|
|
247
|
+
|
|
248
|
+
def _unregister_cpu_buffer(self):
|
|
249
|
+
"""Unregister CPU buffer."""
|
|
250
|
+
if self.registered_buffer_ptr is not None:
|
|
251
|
+
result = self.store.unregister_buffer(self.registered_buffer_ptr)
|
|
252
|
+
if result == 0:
|
|
253
|
+
logger.info(f"Unregistered buffer: {hex(self.registered_buffer_ptr)}")
|
|
254
|
+
else:
|
|
255
|
+
logger.warning(f"Buffer unregistration failed: error={result}")
|
|
256
|
+
self.registered_buffer_ptr = None
|
|
257
|
+
|
|
258
|
+
def support_batched_get(self) -> bool:
|
|
259
|
+
"""
|
|
260
|
+
Check if the connector supports batched get
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
True if batched get is supported, False otherwise
|
|
264
|
+
"""
|
|
265
|
+
return True
|
|
266
|
+
|
|
267
|
+
async def exists(self, key: CacheEngineKey) -> bool:
|
|
268
|
+
return self.store.is_exist(key.to_string())
|
|
269
|
+
|
|
270
|
+
def exists_sync(self, key: CacheEngineKey) -> bool:
|
|
271
|
+
return self.store.is_exist(key.to_string())
|
|
272
|
+
|
|
273
|
+
async def batched_get(
|
|
274
|
+
self, keys: List[CacheEngineKey]
|
|
275
|
+
) -> List[Optional[MemoryObj]]:
|
|
276
|
+
"""
|
|
277
|
+
Batch get operation - the only supported get method.
|
|
278
|
+
Uses batch_get_into (with metadata) or batch_get_buffer (without metadata).
|
|
279
|
+
"""
|
|
280
|
+
if not keys:
|
|
281
|
+
return []
|
|
282
|
+
|
|
283
|
+
# Check if we have metadata for zero-copy operations
|
|
284
|
+
if self.save_chunk_meta:
|
|
285
|
+
# Use legacy mode with metadata stored in remote
|
|
286
|
+
return await self._batch_get_buffer(keys)
|
|
287
|
+
else:
|
|
288
|
+
# Use optimized mode with local metadata
|
|
289
|
+
return await self._batch_get_into(keys)
|
|
290
|
+
|
|
291
|
+
def support_batched_async_contains(self) -> bool:
|
|
292
|
+
return True
|
|
293
|
+
|
|
294
|
+
async def batched_async_contains(
|
|
295
|
+
self,
|
|
296
|
+
lookup_id: str,
|
|
297
|
+
keys: List[CacheEngineKey],
|
|
298
|
+
pin: bool = False,
|
|
299
|
+
) -> int:
|
|
300
|
+
num_hit_counts = 0
|
|
301
|
+
for key in keys:
|
|
302
|
+
if not self.store.is_exist(key.to_string()):
|
|
303
|
+
break
|
|
304
|
+
num_hit_counts += 1
|
|
305
|
+
return num_hit_counts
|
|
306
|
+
|
|
307
|
+
async def _batch_get_into(
|
|
308
|
+
self, keys: List[CacheEngineKey]
|
|
309
|
+
) -> List[Optional[MemoryObj]]:
|
|
310
|
+
"""
|
|
311
|
+
Zero-copy batch get using batch_get_into when metadata is available locally.
|
|
312
|
+
This is used when save_chunk_meta=False (metadata not stored remotely).
|
|
313
|
+
"""
|
|
314
|
+
if not self.meta_shapes or not self.meta_dtypes or not self.meta_fmt:
|
|
315
|
+
logger.error(
|
|
316
|
+
f"Metadata required for batch_get_into but not available: "
|
|
317
|
+
f"meta_shapes={self.meta_shapes}, "
|
|
318
|
+
f"meta_dtypes={self.meta_dtypes}, "
|
|
319
|
+
f"meta_fmt={self.meta_fmt}"
|
|
320
|
+
)
|
|
321
|
+
return [None] * len(keys)
|
|
322
|
+
|
|
323
|
+
logger.debug(f"Using batch_get_into for {len(keys)} keys (zero-copy mode)")
|
|
324
|
+
|
|
325
|
+
# Reserve a buffer for every requested chunk
|
|
326
|
+
memory_objs: list[Optional[MemoryObj]] = []
|
|
327
|
+
valid_idx: list[int] = []
|
|
328
|
+
|
|
329
|
+
key_strs: list[str] = []
|
|
330
|
+
buffer_ptrs: list[int] = []
|
|
331
|
+
buffer_sizes: list[int] = []
|
|
332
|
+
|
|
333
|
+
for i, _ in enumerate(keys):
|
|
334
|
+
obj = self.local_cpu_backend.allocate(
|
|
335
|
+
self.meta_shapes, self.meta_dtypes, self.meta_fmt
|
|
336
|
+
)
|
|
337
|
+
memory_objs.append(obj)
|
|
338
|
+
if obj is not None and obj.raw_tensor is not None:
|
|
339
|
+
valid_idx.append(i)
|
|
340
|
+
|
|
341
|
+
# Prepare the argument lists for the C++ call
|
|
342
|
+
key_strs.append(keys[i].to_string())
|
|
343
|
+
buffer_ptrs.append(obj.data_ptr)
|
|
344
|
+
buffer_sizes.append(obj.get_size())
|
|
345
|
+
|
|
346
|
+
if not valid_idx:
|
|
347
|
+
logger.warning("Batch-get aborted: unable to allocate any buffers.")
|
|
348
|
+
return [None] * len(keys)
|
|
349
|
+
|
|
350
|
+
try:
|
|
351
|
+
# Single RPC call for multiple chunks
|
|
352
|
+
logger.debug(f"Calling batch_get_into with {len(key_strs)} keys")
|
|
353
|
+
bytes_read_list = await asyncio.to_thread(
|
|
354
|
+
self.store.batch_get_into, key_strs, buffer_ptrs, buffer_sizes
|
|
355
|
+
)
|
|
356
|
+
logger.debug(f"batch_get_into returned: {bytes_read_list}")
|
|
357
|
+
|
|
358
|
+
# Assemble the final result list
|
|
359
|
+
results: list[Optional[MemoryObj]] = [None] * len(keys)
|
|
360
|
+
|
|
361
|
+
for i, n_read in zip(valid_idx, bytes_read_list, strict=False):
|
|
362
|
+
if n_read <= 0:
|
|
363
|
+
logger.warning(
|
|
364
|
+
f"batch_get_into failed for key {keys[i]} (code={n_read})"
|
|
365
|
+
)
|
|
366
|
+
memory_objs[i].ref_count_down() # type: ignore
|
|
367
|
+
continue
|
|
368
|
+
|
|
369
|
+
try:
|
|
370
|
+
results[i] = self.reshape_partial_chunk(
|
|
371
|
+
memory_objs[i], # type: ignore
|
|
372
|
+
n_read,
|
|
373
|
+
)
|
|
374
|
+
except Exception as exc:
|
|
375
|
+
logger.error(f"Reshape failed for key {keys[i]}: {exc}")
|
|
376
|
+
memory_objs[i].ref_count_down() # type: ignore
|
|
377
|
+
|
|
378
|
+
return results
|
|
379
|
+
|
|
380
|
+
except Exception as exc:
|
|
381
|
+
logger.error(f"batch_get_into threw exception: {str(exc)}")
|
|
382
|
+
# Release any buffers we successfully allocated
|
|
383
|
+
for i in valid_idx:
|
|
384
|
+
memory_objs[i].ref_count_down() # type: ignore
|
|
385
|
+
return [None] * len(keys)
|
|
386
|
+
|
|
387
|
+
async def _batch_get_buffer(
|
|
388
|
+
self, keys: List[CacheEngineKey]
|
|
389
|
+
) -> List[Optional[MemoryObj]]:
|
|
390
|
+
"""
|
|
391
|
+
Batch get using batch_get_buffer when metadata is stored remotely.
|
|
392
|
+
This is used when save_chunk_meta=True (metadata stored with data).
|
|
393
|
+
"""
|
|
394
|
+
key_strs = [key.to_string() for key in keys]
|
|
395
|
+
|
|
396
|
+
try:
|
|
397
|
+
buffers = await asyncio.to_thread(self.store.batch_get_buffer, key_strs)
|
|
398
|
+
except Exception as e:
|
|
399
|
+
logger.error(f"batch_get_buffer failed: {str(e)}")
|
|
400
|
+
return [None] * len(keys)
|
|
401
|
+
|
|
402
|
+
results: list[Optional[MemoryObj]] = []
|
|
403
|
+
for i, buffer in enumerate(buffers):
|
|
404
|
+
if buffer is None:
|
|
405
|
+
logger.warning(f"Buffer {i} is None for key {key_strs[i]}")
|
|
406
|
+
results.append(None)
|
|
407
|
+
continue
|
|
408
|
+
try:
|
|
409
|
+
memory_obj = self._process_buffer_with_metadata(buffer)
|
|
410
|
+
results.append(memory_obj)
|
|
411
|
+
except Exception as e:
|
|
412
|
+
logger.error(
|
|
413
|
+
f"Failed to process buffer {i} for key {key_strs[i]}: {str(e)}"
|
|
414
|
+
)
|
|
415
|
+
results.append(None)
|
|
416
|
+
return results
|
|
417
|
+
|
|
418
|
+
async def get(self, key: CacheEngineKey) -> Optional[MemoryObj]:
|
|
419
|
+
"""
|
|
420
|
+
Single get method - NOT SUPPORTED.
|
|
421
|
+
Use batched_get instead for all operations.
|
|
422
|
+
"""
|
|
423
|
+
logger.error("Single get operation is not supported. Use batched_get instead.")
|
|
424
|
+
raise NotImplementedError(
|
|
425
|
+
"Single get is not supported. Use batched_get([key]) instead."
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
def _process_buffer_with_metadata(self, buffer: bytes) -> Optional[MemoryObj]:
|
|
429
|
+
"""
|
|
430
|
+
Process buffer that contains metadata + data.
|
|
431
|
+
Used when save_chunk_meta=True (metadata stored remotely).
|
|
432
|
+
"""
|
|
433
|
+
retrieved_view = memoryview(buffer)
|
|
434
|
+
metadata_bytes = retrieved_view[: self.remote_metadata_bytes]
|
|
435
|
+
if metadata_bytes is None or len(metadata_bytes) != self.remote_metadata_bytes:
|
|
436
|
+
return None
|
|
437
|
+
|
|
438
|
+
metadata = RemoteMetadata.deserialize(metadata_bytes)
|
|
439
|
+
|
|
440
|
+
memory_obj = self.local_cpu_backend.allocate(
|
|
441
|
+
metadata.shapes,
|
|
442
|
+
metadata.dtypes,
|
|
443
|
+
metadata.fmt,
|
|
444
|
+
)
|
|
445
|
+
assert len(retrieved_view) == metadata.length + self.remote_metadata_bytes
|
|
446
|
+
|
|
447
|
+
if memory_obj is None:
|
|
448
|
+
logger.warning("Failed to allocate memory during remote receive")
|
|
449
|
+
return None
|
|
450
|
+
|
|
451
|
+
if memory_obj.raw_tensor is not None:
|
|
452
|
+
temp_tensor = torch.frombuffer(
|
|
453
|
+
buffer,
|
|
454
|
+
dtype=torch.uint8,
|
|
455
|
+
offset=self.remote_metadata_bytes,
|
|
456
|
+
count=metadata.length,
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
memory_obj.raw_tensor.copy_(temp_tensor)
|
|
460
|
+
return memory_obj
|
|
461
|
+
else:
|
|
462
|
+
return None
|
|
463
|
+
|
|
464
|
+
async def put(self, key: CacheEngineKey, memory_obj: MemoryObj):
|
|
465
|
+
"""
|
|
466
|
+
Put operation with metadata-consistent handling.
|
|
467
|
+
Uses put_from (without metadata) or
|
|
468
|
+
put_parts (with metadata) to match get behavior.
|
|
469
|
+
"""
|
|
470
|
+
key_str = key.to_string()
|
|
471
|
+
|
|
472
|
+
# Check metadata handling mode to match get behavior
|
|
473
|
+
if self.save_chunk_meta:
|
|
474
|
+
# Use put_parts with metadata stored remotely
|
|
475
|
+
await self._put_with_metadata(key_str, memory_obj)
|
|
476
|
+
else:
|
|
477
|
+
# Use put_from without metadata (zero-copy)
|
|
478
|
+
await self._put_without_metadata(key_str, memory_obj)
|
|
479
|
+
|
|
480
|
+
def support_batched_put(self) -> bool:
|
|
481
|
+
return True
|
|
482
|
+
|
|
483
|
+
async def batched_put(
|
|
484
|
+
self,
|
|
485
|
+
keys: List[CacheEngineKey],
|
|
486
|
+
memory_objs: List[MemoryObj],
|
|
487
|
+
):
|
|
488
|
+
"""
|
|
489
|
+
Batched put with clear split by metadata mode.
|
|
490
|
+
- save_chunk_meta False: use Mooncake's batch_put_from (zero-copy).
|
|
491
|
+
- save_chunk_meta True: no batch API; fall back to sequential put_parts.
|
|
492
|
+
"""
|
|
493
|
+
if not keys:
|
|
494
|
+
return
|
|
495
|
+
|
|
496
|
+
if self.save_chunk_meta:
|
|
497
|
+
await self._batched_put_with_metadata(keys, memory_objs)
|
|
498
|
+
else:
|
|
499
|
+
await self._batched_put_zero_copy(keys, memory_objs)
|
|
500
|
+
|
|
501
|
+
async def _batched_put_zero_copy(
|
|
502
|
+
self,
|
|
503
|
+
keys: List[CacheEngineKey],
|
|
504
|
+
memory_objs: List[MemoryObj],
|
|
505
|
+
) -> None:
|
|
506
|
+
key_strs = [k.to_string() for k in keys]
|
|
507
|
+
buffer_ptrs: list[int] = []
|
|
508
|
+
buffer_sizes: list[int] = []
|
|
509
|
+
for obj in memory_objs:
|
|
510
|
+
assert obj.raw_tensor is not None
|
|
511
|
+
buffer_ptrs.append(obj.data_ptr)
|
|
512
|
+
buffer_sizes.append(obj.get_size())
|
|
513
|
+
|
|
514
|
+
try:
|
|
515
|
+
await asyncio.wait_for(
|
|
516
|
+
asyncio.to_thread(
|
|
517
|
+
self.store.batch_put_from,
|
|
518
|
+
key_strs,
|
|
519
|
+
buffer_ptrs,
|
|
520
|
+
buffer_sizes,
|
|
521
|
+
self.replica_config,
|
|
522
|
+
),
|
|
523
|
+
timeout=self.config.transfer_timeout,
|
|
524
|
+
)
|
|
525
|
+
except asyncio.TimeoutError:
|
|
526
|
+
logger.warning(
|
|
527
|
+
"Timeout during batch_put_from; some decoders may redo prefill."
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
async def _batched_put_with_metadata(
|
|
531
|
+
self,
|
|
532
|
+
keys: List[CacheEngineKey],
|
|
533
|
+
memory_objs: List[MemoryObj],
|
|
534
|
+
) -> None:
|
|
535
|
+
for key, obj in zip(keys, memory_objs, strict=False):
|
|
536
|
+
await self._put_with_metadata(key.to_string(), obj)
|
|
537
|
+
|
|
538
|
+
async def _put_without_metadata(self, key_str: str, memory_obj: MemoryObj):
|
|
539
|
+
"""
|
|
540
|
+
Zero-copy put using put_from when metadata is not stored remotely.
|
|
541
|
+
This is used when save_chunk_meta=False (matches _batch_get_into).
|
|
542
|
+
"""
|
|
543
|
+
try:
|
|
544
|
+
assert memory_obj.raw_tensor is not None
|
|
545
|
+
buffer_ptr = memory_obj.data_ptr
|
|
546
|
+
buffer_size = memory_obj.get_size()
|
|
547
|
+
|
|
548
|
+
await asyncio.wait_for(
|
|
549
|
+
asyncio.to_thread(
|
|
550
|
+
self.store.put_from,
|
|
551
|
+
key_str,
|
|
552
|
+
buffer_ptr,
|
|
553
|
+
buffer_size,
|
|
554
|
+
self.replica_config,
|
|
555
|
+
),
|
|
556
|
+
timeout=self.config.transfer_timeout,
|
|
557
|
+
)
|
|
558
|
+
except asyncio.TimeoutError:
|
|
559
|
+
logger.warning(
|
|
560
|
+
f"Timeout when putting key {key_str} using put_from. "
|
|
561
|
+
"Decode instance may redo prefill."
|
|
562
|
+
)
|
|
563
|
+
except Exception as e:
|
|
564
|
+
logger.error(
|
|
565
|
+
f"Failed to put key {key_str} using put_from: "
|
|
566
|
+
f"{type(e).__name__}: {str(e)}"
|
|
567
|
+
)
|
|
568
|
+
raise
|
|
569
|
+
|
|
570
|
+
async def _put_with_metadata(self, key_str: str, memory_obj: MemoryObj):
|
|
571
|
+
"""
|
|
572
|
+
Put using put_parts when metadata is stored remotely.
|
|
573
|
+
This is used when save_chunk_meta=True (matches _batch_get_buffer).
|
|
574
|
+
"""
|
|
575
|
+
try:
|
|
576
|
+
# Serialize data and metadata
|
|
577
|
+
kv_bytes = memory_obj.byte_array
|
|
578
|
+
kv_shapes = memory_obj.get_shapes()
|
|
579
|
+
kv_dtypes = memory_obj.get_dtypes()
|
|
580
|
+
memory_format = memory_obj.get_memory_format()
|
|
581
|
+
|
|
582
|
+
metadata_bytes = RemoteMetadata(
|
|
583
|
+
len(kv_bytes), kv_shapes, kv_dtypes, memory_format
|
|
584
|
+
).serialize()
|
|
585
|
+
assert len(metadata_bytes) == self.remote_metadata_bytes
|
|
586
|
+
|
|
587
|
+
await asyncio.wait_for(
|
|
588
|
+
asyncio.to_thread(
|
|
589
|
+
self.store.put_parts, key_str, metadata_bytes, kv_bytes
|
|
590
|
+
),
|
|
591
|
+
timeout=self.config.transfer_timeout,
|
|
592
|
+
)
|
|
593
|
+
except asyncio.TimeoutError:
|
|
594
|
+
logger.warning(
|
|
595
|
+
f"Timeout when putting key {key_str} using put_parts. "
|
|
596
|
+
"Decode instance may redo prefill."
|
|
597
|
+
)
|
|
598
|
+
except Exception as e:
|
|
599
|
+
logger.error(
|
|
600
|
+
f"Failed to put key {key_str} using put_parts: "
|
|
601
|
+
f"{type(e).__name__}: {str(e)}"
|
|
602
|
+
)
|
|
603
|
+
raise
|
|
604
|
+
|
|
605
|
+
@no_type_check
|
|
606
|
+
async def list(self) -> List[str]:
|
|
607
|
+
pass
|
|
608
|
+
|
|
609
|
+
async def close(self):
|
|
610
|
+
# Unregister buffer before closing the store
|
|
611
|
+
self._unregister_cpu_buffer()
|
|
612
|
+
|
|
613
|
+
self.store.close()
|
|
614
|
+
logger.info("Closed the mooncake store connection")
|