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,19 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
# Third Party
|
|
6
|
+
import msgspec
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class LMCacheModelRequest(
|
|
10
|
+
msgspec.Struct,
|
|
11
|
+
array_like=True, # type: ignore[call-arg]
|
|
12
|
+
omit_defaults=True,
|
|
13
|
+
): # type: ignore[call-arg]
|
|
14
|
+
"""
|
|
15
|
+
User-provided information to control the cache behavior.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
store_cache: bool = True # Whether to store the cache
|
|
19
|
+
ttl: Optional[float] = None # Time to live
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Check mode registry implementation"""
|
|
3
|
+
|
|
4
|
+
# Standard
|
|
5
|
+
from typing import Callable, Dict, Optional
|
|
6
|
+
import importlib
|
|
7
|
+
import inspect
|
|
8
|
+
import os
|
|
9
|
+
|
|
10
|
+
# First Party
|
|
11
|
+
from lmcache.logging import init_logger
|
|
12
|
+
|
|
13
|
+
logger = init_logger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CheckModeRegistry:
|
|
17
|
+
"""Registry for dynamically loaded check modes"""
|
|
18
|
+
|
|
19
|
+
def __init__(self):
|
|
20
|
+
self.modes: Dict[str, Callable] = {}
|
|
21
|
+
self.loaded = False
|
|
22
|
+
|
|
23
|
+
def register(self, name: str, func: Callable):
|
|
24
|
+
"""Register a check mode function"""
|
|
25
|
+
if name in self.modes:
|
|
26
|
+
raise ValueError(f"Check mode '{name}' already registered")
|
|
27
|
+
self.modes[name] = func
|
|
28
|
+
|
|
29
|
+
def load_modes(self):
|
|
30
|
+
"""Dynamically load all check mode modules"""
|
|
31
|
+
if self.loaded:
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
# Get current package
|
|
35
|
+
current_dir = os.path.dirname(__file__)
|
|
36
|
+
|
|
37
|
+
# Find all modules with check_mode_ prefix
|
|
38
|
+
for filename in os.listdir(current_dir):
|
|
39
|
+
if filename.startswith("check_mode_") and filename.endswith(".py"):
|
|
40
|
+
module_name = filename[:-3] # Remove .py
|
|
41
|
+
try:
|
|
42
|
+
module = importlib.import_module(
|
|
43
|
+
f".{module_name}", package=__package__
|
|
44
|
+
)
|
|
45
|
+
# Find and register mode functions
|
|
46
|
+
for name, obj in inspect.getmembers(module):
|
|
47
|
+
if inspect.isfunction(obj) and hasattr(obj, "is_check_mode"):
|
|
48
|
+
self.register(obj.mode_name, obj)
|
|
49
|
+
except ImportError as e:
|
|
50
|
+
logger.error(f"Failed to load check mode module {module_name}: {e}")
|
|
51
|
+
|
|
52
|
+
self.loaded = True
|
|
53
|
+
logger.info(f"Loaded {len(self.modes)} check modes")
|
|
54
|
+
|
|
55
|
+
def get_mode(self, name: str) -> Optional[Callable]:
|
|
56
|
+
"""Get registered mode function. Returns None if the mode is not found."""
|
|
57
|
+
if not self.loaded:
|
|
58
|
+
self.load_modes()
|
|
59
|
+
return self.modes.get(name)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def check_mode(name: str):
|
|
63
|
+
"""Decorator to mark functions as check modes"""
|
|
64
|
+
|
|
65
|
+
def decorator(func):
|
|
66
|
+
func.is_check_mode = True
|
|
67
|
+
func.mode_name = name
|
|
68
|
+
return func
|
|
69
|
+
|
|
70
|
+
return decorator
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# Global registry instance
|
|
74
|
+
registry = CheckModeRegistry()
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Generate mode implementation for key generation"""
|
|
3
|
+
|
|
4
|
+
# Third Party
|
|
5
|
+
import tqdm
|
|
6
|
+
|
|
7
|
+
# First Party
|
|
8
|
+
from lmcache.v1.check import check_mode
|
|
9
|
+
from lmcache.v1.check.utils import (
|
|
10
|
+
_get_default_metadata,
|
|
11
|
+
create_memory_objects_batch,
|
|
12
|
+
create_storage_manager_with_config,
|
|
13
|
+
create_test_key,
|
|
14
|
+
find_remote_backend,
|
|
15
|
+
flow_control_check,
|
|
16
|
+
wait_put_tasks_complete,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@check_mode("gen")
|
|
21
|
+
async def run_gen_mode(
|
|
22
|
+
model: str, num_keys: int, concurrency: int, offset: int = 0, **kwargs
|
|
23
|
+
):
|
|
24
|
+
"""Run key generation mode"""
|
|
25
|
+
# Create storage manager using common function
|
|
26
|
+
storage_manager = create_storage_manager_with_config(model)
|
|
27
|
+
metadata = _get_default_metadata(model)
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
print("Generate: Passed - Created storage manager with valid config")
|
|
31
|
+
|
|
32
|
+
# Find remote backend for flow control
|
|
33
|
+
remote_backend = find_remote_backend(storage_manager)
|
|
34
|
+
|
|
35
|
+
# Create limited number of memory objects for reuse (memory efficiency)
|
|
36
|
+
batch_size = min(concurrency, 100) # Limit to 100 for memory efficiency
|
|
37
|
+
memory_objs = create_memory_objects_batch(storage_manager, metadata, batch_size)
|
|
38
|
+
|
|
39
|
+
if not memory_objs:
|
|
40
|
+
print("Generate: Failed - Could not allocate any memory objects")
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
# Create progress bar
|
|
44
|
+
progress_bar = tqdm.tqdm(
|
|
45
|
+
total=num_keys, desc="Generating keys", unit="key", unit_scale=True
|
|
46
|
+
)
|
|
47
|
+
sleep_count = 1.0
|
|
48
|
+
# Process keys in batches of concurrency size
|
|
49
|
+
for batch_start in range(0, num_keys, concurrency):
|
|
50
|
+
batch_end = min(batch_start + concurrency, num_keys)
|
|
51
|
+
batch_keys = []
|
|
52
|
+
batch_memory_objs = []
|
|
53
|
+
|
|
54
|
+
# Create keys and reuse memory objects for this batch
|
|
55
|
+
for i in range(batch_start, batch_end):
|
|
56
|
+
key = create_test_key(model, f"gen_{offset + i}")
|
|
57
|
+
# Reuse memory objects in round-robin fashion
|
|
58
|
+
memory_obj = memory_objs[i % len(memory_objs)]
|
|
59
|
+
batch_keys.append(key)
|
|
60
|
+
batch_memory_objs.append(memory_obj)
|
|
61
|
+
memory_obj.ref_count_up()
|
|
62
|
+
|
|
63
|
+
# Flow control: check if remote backend has too many pending tasks
|
|
64
|
+
sleep_count = await flow_control_check(
|
|
65
|
+
remote_backend, concurrency, sleep_count
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
# Use batched_put to store the batch of memory objects
|
|
69
|
+
storage_manager.batched_put(batch_keys, batch_memory_objs)
|
|
70
|
+
|
|
71
|
+
# Update progress bar
|
|
72
|
+
progress_bar.update(len(batch_keys))
|
|
73
|
+
|
|
74
|
+
progress_bar.close()
|
|
75
|
+
print(f"Generate: Successfully generated {num_keys} keys")
|
|
76
|
+
|
|
77
|
+
# Wait for remote backend put_tasks to complete
|
|
78
|
+
wait_put_tasks_complete(find_remote_backend(storage_manager))
|
|
79
|
+
|
|
80
|
+
except Exception as e:
|
|
81
|
+
print(
|
|
82
|
+
f"Generate: Failed - Error creating storage manager with valid config: {e}"
|
|
83
|
+
)
|
|
84
|
+
finally:
|
|
85
|
+
if storage_manager:
|
|
86
|
+
storage_manager.close()
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Test mode implementation for MP mode L2 adapter basic checks"""
|
|
3
|
+
|
|
4
|
+
# Standard
|
|
5
|
+
import argparse
|
|
6
|
+
import os
|
|
7
|
+
import select
|
|
8
|
+
import time
|
|
9
|
+
|
|
10
|
+
# Third Party
|
|
11
|
+
import torch
|
|
12
|
+
|
|
13
|
+
# First Party
|
|
14
|
+
from lmcache.v1.check import check_mode
|
|
15
|
+
from lmcache.v1.check.utils import (
|
|
16
|
+
DEFAULT_KV_DTYPE_STR,
|
|
17
|
+
DEFAULT_OBJ_SIZE,
|
|
18
|
+
parse_kv_dtype,
|
|
19
|
+
print_performance_results,
|
|
20
|
+
)
|
|
21
|
+
from lmcache.v1.distributed.api import ObjectKey
|
|
22
|
+
from lmcache.v1.distributed.l2_adapters import create_l2_adapter
|
|
23
|
+
from lmcache.v1.distributed.l2_adapters.config import (
|
|
24
|
+
parse_args_to_l2_adapters_config,
|
|
25
|
+
)
|
|
26
|
+
from lmcache.v1.memory_management import (
|
|
27
|
+
MemoryFormat,
|
|
28
|
+
MemoryObjMetadata,
|
|
29
|
+
TensorMemoryObj,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
_POLL_TIMEOUT_MS = 100000
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _create_object_key(model: str, key_id: str) -> ObjectKey:
|
|
36
|
+
"""Create a test ObjectKey."""
|
|
37
|
+
return ObjectKey(
|
|
38
|
+
chunk_hash=ObjectKey.IntHash2Bytes(hash(key_id) & 0xFFFFFFFF),
|
|
39
|
+
model_name=model,
|
|
40
|
+
kv_rank=0,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _create_memory_obj(
|
|
45
|
+
fill_value: float = 0.0,
|
|
46
|
+
obj_size: int = DEFAULT_OBJ_SIZE,
|
|
47
|
+
dtype: torch.dtype = torch.float32,
|
|
48
|
+
) -> TensorMemoryObj:
|
|
49
|
+
"""Create a test TensorMemoryObj."""
|
|
50
|
+
raw_data = torch.empty(obj_size, dtype=dtype)
|
|
51
|
+
raw_data.fill_(fill_value)
|
|
52
|
+
metadata = MemoryObjMetadata(
|
|
53
|
+
shape=torch.Size([obj_size]),
|
|
54
|
+
dtype=dtype,
|
|
55
|
+
address=0,
|
|
56
|
+
phy_size=obj_size * raw_data.element_size(),
|
|
57
|
+
fmt=MemoryFormat.KV_2LTD,
|
|
58
|
+
ref_count=1,
|
|
59
|
+
)
|
|
60
|
+
return TensorMemoryObj(raw_data, metadata, parent_allocator=None)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _wait_event_fd(efd: int, timeout_ms: int = _POLL_TIMEOUT_MS) -> bool:
|
|
64
|
+
"""Wait for an eventfd to be signaled."""
|
|
65
|
+
poll = select.poll()
|
|
66
|
+
poll.register(efd, select.POLLIN)
|
|
67
|
+
events = poll.poll(timeout_ms)
|
|
68
|
+
if events:
|
|
69
|
+
try:
|
|
70
|
+
os.eventfd_read(efd)
|
|
71
|
+
except BlockingIOError:
|
|
72
|
+
pass
|
|
73
|
+
return True
|
|
74
|
+
return False
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _run_store_phase(adapter, keys, objects):
|
|
78
|
+
"""Run store phase and return (stats, success)."""
|
|
79
|
+
efd = adapter.get_store_event_fd()
|
|
80
|
+
start = time.perf_counter()
|
|
81
|
+
task_id = adapter.submit_store_task(keys, objects)
|
|
82
|
+
if not _wait_event_fd(efd):
|
|
83
|
+
print(" Store: timed out waiting for eventfd")
|
|
84
|
+
return None, False
|
|
85
|
+
completed = adapter.pop_completed_store_tasks()
|
|
86
|
+
elapsed_ms = (time.perf_counter() - start) * 1000
|
|
87
|
+
ok = completed.get(task_id, False)
|
|
88
|
+
return elapsed_ms, ok
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _run_lookup_phase(adapter, keys):
|
|
92
|
+
"""Run lookup phase and return (stats, bitmap)."""
|
|
93
|
+
efd = adapter.get_lookup_and_lock_event_fd()
|
|
94
|
+
start = time.perf_counter()
|
|
95
|
+
task_id = adapter.submit_lookup_and_lock_task(keys)
|
|
96
|
+
if not _wait_event_fd(efd):
|
|
97
|
+
print(" Lookup: timed out waiting for eventfd")
|
|
98
|
+
return None, None
|
|
99
|
+
bitmap = adapter.query_lookup_and_lock_result(task_id)
|
|
100
|
+
elapsed_ms = (time.perf_counter() - start) * 1000
|
|
101
|
+
return elapsed_ms, bitmap
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _run_load_phase(adapter, keys, buffers):
|
|
105
|
+
"""Run load phase and return (stats, bitmap)."""
|
|
106
|
+
efd = adapter.get_load_event_fd()
|
|
107
|
+
start = time.perf_counter()
|
|
108
|
+
task_id = adapter.submit_load_task(keys, buffers)
|
|
109
|
+
if not _wait_event_fd(efd):
|
|
110
|
+
print(" Load: timed out waiting for eventfd")
|
|
111
|
+
return None, None
|
|
112
|
+
bitmap = adapter.query_load_result(task_id)
|
|
113
|
+
elapsed_ms = (time.perf_counter() - start) * 1000
|
|
114
|
+
return elapsed_ms, bitmap
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@check_mode("test_l2_adapter")
|
|
118
|
+
async def run_test_mode(model: str, **kwargs):
|
|
119
|
+
"""Run L2 adapter test mode.
|
|
120
|
+
|
|
121
|
+
Requires ``l2_adapter`` in *kwargs* (list of JSON
|
|
122
|
+
strings from ``--l2-adapter``).
|
|
123
|
+
"""
|
|
124
|
+
l2_adapter_raw = kwargs.get("l2_adapter")
|
|
125
|
+
if not l2_adapter_raw:
|
|
126
|
+
print("Error: --l2-adapter is required for test_l2_adapter mode")
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
obj_size = kwargs.get("obj_size") or DEFAULT_OBJ_SIZE
|
|
130
|
+
kv_dtype_str = kwargs.get("kv_dtype") or DEFAULT_KV_DTYPE_STR
|
|
131
|
+
kv_dtype = parse_kv_dtype(kv_dtype_str)
|
|
132
|
+
if kv_dtype is None:
|
|
133
|
+
print("Error: unsupported --kv-dtype '%s'" % kv_dtype_str)
|
|
134
|
+
return
|
|
135
|
+
|
|
136
|
+
# Build adapter config via the standard parser
|
|
137
|
+
ns = argparse.Namespace(l2_adapter=l2_adapter_raw)
|
|
138
|
+
l2_cfg = parse_args_to_l2_adapters_config(ns)
|
|
139
|
+
if not l2_cfg.adapters:
|
|
140
|
+
print("Error: no L2 adapter configs parsed")
|
|
141
|
+
return
|
|
142
|
+
|
|
143
|
+
num_tests = kwargs.get("num_keys", 5)
|
|
144
|
+
settle_time = kwargs.get("settle_time", 0.0)
|
|
145
|
+
|
|
146
|
+
for idx, adapter_cfg in enumerate(l2_cfg.adapters):
|
|
147
|
+
adapter = create_l2_adapter(adapter_cfg)
|
|
148
|
+
print("=== Testing L2 adapter #%d (%s) ===" % (idx, type(adapter).__name__))
|
|
149
|
+
|
|
150
|
+
try:
|
|
151
|
+
_test_single_adapter(
|
|
152
|
+
adapter,
|
|
153
|
+
model,
|
|
154
|
+
num_tests,
|
|
155
|
+
obj_size=obj_size,
|
|
156
|
+
kv_dtype=kv_dtype,
|
|
157
|
+
settle_time=settle_time,
|
|
158
|
+
)
|
|
159
|
+
except Exception as e:
|
|
160
|
+
print(" Test Failed - Error: %s" % e)
|
|
161
|
+
finally:
|
|
162
|
+
adapter.close()
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _test_single_adapter(
|
|
166
|
+
adapter,
|
|
167
|
+
model,
|
|
168
|
+
num_tests,
|
|
169
|
+
obj_size=DEFAULT_OBJ_SIZE,
|
|
170
|
+
kv_dtype=torch.float32,
|
|
171
|
+
settle_time=0.0,
|
|
172
|
+
):
|
|
173
|
+
"""Run all test phases against one adapter."""
|
|
174
|
+
# -- Prepare test data -----------------------------------
|
|
175
|
+
exist_keys = [_create_object_key(model, "exist_%d" % i) for i in range(num_tests)]
|
|
176
|
+
non_exist_keys = [
|
|
177
|
+
_create_object_key(model, "nonexist_%d" % i) for i in range(num_tests)
|
|
178
|
+
]
|
|
179
|
+
store_objs = [
|
|
180
|
+
_create_memory_obj(float(i + 1), obj_size, kv_dtype) for i in range(num_tests)
|
|
181
|
+
]
|
|
182
|
+
|
|
183
|
+
# -- Phase 1: lookup non-existing keys -------------------
|
|
184
|
+
print("Phase 1: Lookup non-existing keys...")
|
|
185
|
+
lk_absent_ms, lk_bitmap = _run_lookup_phase(adapter, non_exist_keys)
|
|
186
|
+
if lk_bitmap is None:
|
|
187
|
+
print(" FAIL: lookup returned None bitmap")
|
|
188
|
+
ne_pass = 0
|
|
189
|
+
else:
|
|
190
|
+
ne_pass = sum(1 for i in range(num_tests) if not lk_bitmap.test(i))
|
|
191
|
+
print(" Validation: %d/%d correctly absent" % (ne_pass, num_tests))
|
|
192
|
+
# Unlock the looked-up keys (contract)
|
|
193
|
+
adapter.submit_unlock(non_exist_keys)
|
|
194
|
+
|
|
195
|
+
# -- Phase 2: store existing keys ------------------------
|
|
196
|
+
print("Phase 2: Store operations (batch of %d)..." % num_tests)
|
|
197
|
+
st_ms, st_ok = _run_store_phase(adapter, exist_keys, store_objs)
|
|
198
|
+
store_pass = num_tests if st_ok else 0
|
|
199
|
+
print(" Batch store %s (%.2fms)" % ("OK" if st_ok else "FAIL", st_ms or 0))
|
|
200
|
+
|
|
201
|
+
if settle_time > 0:
|
|
202
|
+
print(" Waiting %.1fs for data to settle..." % settle_time)
|
|
203
|
+
time.sleep(settle_time)
|
|
204
|
+
|
|
205
|
+
# -- Phase 3: lookup existing keys -----------------------
|
|
206
|
+
print("Phase 3: Lookup existing keys...")
|
|
207
|
+
lk_exist_ms, lk_bitmap = _run_lookup_phase(adapter, exist_keys)
|
|
208
|
+
if lk_bitmap is None:
|
|
209
|
+
print(" FAIL: lookup returned None bitmap")
|
|
210
|
+
exist_pass = 0
|
|
211
|
+
else:
|
|
212
|
+
exist_pass = sum(1 for i in range(num_tests) if lk_bitmap.test(i))
|
|
213
|
+
print(" Validation: %d/%d found" % (exist_pass, num_tests))
|
|
214
|
+
|
|
215
|
+
# -- Phase 4: load existing keys -------------------------
|
|
216
|
+
print("Phase 4: Load operations...")
|
|
217
|
+
load_buffers = [
|
|
218
|
+
_create_memory_obj(0.0, obj_size, kv_dtype) for _ in range(num_tests)
|
|
219
|
+
]
|
|
220
|
+
ld_ms, ld_bitmap = _run_load_phase(adapter, exist_keys, load_buffers)
|
|
221
|
+
load_pass = 0
|
|
222
|
+
content_pass = 0
|
|
223
|
+
if ld_bitmap is not None:
|
|
224
|
+
for i in range(num_tests):
|
|
225
|
+
if ld_bitmap.test(i):
|
|
226
|
+
load_pass += 1
|
|
227
|
+
if torch.equal(
|
|
228
|
+
load_buffers[i].tensor,
|
|
229
|
+
store_objs[i].tensor,
|
|
230
|
+
):
|
|
231
|
+
content_pass += 1
|
|
232
|
+
else:
|
|
233
|
+
print(" Key %d: data mismatch" % i)
|
|
234
|
+
print(" Validation (loaded): %d/%d" % (load_pass, num_tests))
|
|
235
|
+
print(" Validation (content): %d/%d" % (content_pass, num_tests))
|
|
236
|
+
|
|
237
|
+
# Unlock after load
|
|
238
|
+
adapter.submit_unlock(exist_keys)
|
|
239
|
+
|
|
240
|
+
# -- Summary ---------------------------------------------
|
|
241
|
+
total_bytes = obj_size * store_objs[0].tensor.element_size() * num_tests
|
|
242
|
+
stats_data = [
|
|
243
|
+
(
|
|
244
|
+
"LOOKUP (absent)",
|
|
245
|
+
{
|
|
246
|
+
"avg": lk_absent_ms or 0,
|
|
247
|
+
"max": lk_absent_ms or 0,
|
|
248
|
+
"min": lk_absent_ms or 0,
|
|
249
|
+
},
|
|
250
|
+
[False] * num_tests,
|
|
251
|
+
ne_pass,
|
|
252
|
+
),
|
|
253
|
+
(
|
|
254
|
+
"STORE",
|
|
255
|
+
{
|
|
256
|
+
"avg": st_ms or 0,
|
|
257
|
+
"max": st_ms or 0,
|
|
258
|
+
"min": st_ms or 0,
|
|
259
|
+
},
|
|
260
|
+
[True] * store_pass + [False] * (num_tests - store_pass),
|
|
261
|
+
store_pass,
|
|
262
|
+
),
|
|
263
|
+
(
|
|
264
|
+
"LOOKUP (exist)",
|
|
265
|
+
{
|
|
266
|
+
"avg": lk_exist_ms or 0,
|
|
267
|
+
"max": lk_exist_ms or 0,
|
|
268
|
+
"min": lk_exist_ms or 0,
|
|
269
|
+
},
|
|
270
|
+
[True] * exist_pass + [False] * (num_tests - exist_pass),
|
|
271
|
+
exist_pass,
|
|
272
|
+
),
|
|
273
|
+
(
|
|
274
|
+
"LOAD",
|
|
275
|
+
{
|
|
276
|
+
"avg": ld_ms or 0,
|
|
277
|
+
"max": ld_ms or 0,
|
|
278
|
+
"min": ld_ms or 0,
|
|
279
|
+
},
|
|
280
|
+
[True] * content_pass + [False] * (num_tests - content_pass),
|
|
281
|
+
content_pass,
|
|
282
|
+
),
|
|
283
|
+
]
|
|
284
|
+
print_performance_results(stats_data, obj_bytes=total_bytes)
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
"""Test mode implementation for basic checks"""
|
|
3
|
+
|
|
4
|
+
# Standard
|
|
5
|
+
import asyncio
|
|
6
|
+
|
|
7
|
+
# First Party
|
|
8
|
+
from lmcache.integration.vllm.utils import lmcache_get_or_create_config
|
|
9
|
+
from lmcache.v1.check import check_mode
|
|
10
|
+
|
|
11
|
+
# Import shared utilities
|
|
12
|
+
from lmcache.v1.check.utils import (
|
|
13
|
+
DEFAULT_KV_DTYPE_STR,
|
|
14
|
+
EventLoopManager,
|
|
15
|
+
_get_default_metadata,
|
|
16
|
+
create_test_key,
|
|
17
|
+
parse_kv_dtype,
|
|
18
|
+
run_common_test_framework,
|
|
19
|
+
validate_get_results,
|
|
20
|
+
)
|
|
21
|
+
from lmcache.v1.memory_management import MemoryObj
|
|
22
|
+
|
|
23
|
+
# Import from lmcache with absolute paths
|
|
24
|
+
from lmcache.v1.storage_backend import RemoteBackend
|
|
25
|
+
from lmcache.v1.storage_backend.connector import InstrumentedRemoteConnector
|
|
26
|
+
from lmcache.v1.storage_backend.local_cpu_backend import LocalCPUBackend
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
async def async_contains_backend(backend, key):
|
|
30
|
+
"""Async wrapper for backend contains method"""
|
|
31
|
+
return backend.contains(key)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
async def async_get_backend(backend, key):
|
|
35
|
+
"""Async wrapper for backend get_blocking method"""
|
|
36
|
+
return backend.get_blocking(key)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
async def async_submit_put_backend(backend, key, memory_obj):
|
|
40
|
+
"""Async wrapper for backend submit_put_task"""
|
|
41
|
+
future = backend.submit_put_task(key, memory_obj)
|
|
42
|
+
# Wait for the future to complete with timeout
|
|
43
|
+
try:
|
|
44
|
+
await asyncio.wait_for(asyncio.wrap_future(future), timeout=10.0)
|
|
45
|
+
return True
|
|
46
|
+
except asyncio.TimeoutError:
|
|
47
|
+
print(f"Put task timed out for key: {key}")
|
|
48
|
+
return False
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def create_test_memory_obj(
|
|
52
|
+
backend: RemoteBackend, local_cpu_backend: LocalCPUBackend
|
|
53
|
+
) -> MemoryObj:
|
|
54
|
+
"""Create a test MemoryObj for testing."""
|
|
55
|
+
if backend.connection is None:
|
|
56
|
+
raise ValueError("Backend connection is None")
|
|
57
|
+
|
|
58
|
+
if isinstance(backend.connection, InstrumentedRemoteConnector):
|
|
59
|
+
connector = backend.connection.getWrappedConnector()
|
|
60
|
+
else:
|
|
61
|
+
connector = backend.connection
|
|
62
|
+
|
|
63
|
+
return local_cpu_backend.allocate(
|
|
64
|
+
connector.meta_shapes, connector.meta_dtypes, connector.meta_fmt
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def create_test_data_for_backend(
|
|
69
|
+
backend,
|
|
70
|
+
local_cpu_backend,
|
|
71
|
+
model,
|
|
72
|
+
num_tests,
|
|
73
|
+
kv_dtype=None,
|
|
74
|
+
):
|
|
75
|
+
"""Create test data for backend based tests"""
|
|
76
|
+
# Group 1: Non-existing keys
|
|
77
|
+
kw = {} if kv_dtype is None else {"kv_dtype": kv_dtype}
|
|
78
|
+
non_exist_keys = [
|
|
79
|
+
create_test_key(model, f"non_exist_{i}", **kw) for i in range(num_tests)
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
# Group 2: Existing keys
|
|
83
|
+
exist_keys = [create_test_key(model, f"exist_{i}", **kw) for i in range(num_tests)]
|
|
84
|
+
exist_memories = [
|
|
85
|
+
create_test_memory_obj(backend, local_cpu_backend) for _ in range(num_tests)
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
return non_exist_keys, exist_keys, exist_memories, num_tests
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@check_mode("test_remote")
|
|
92
|
+
async def run_test_mode(model: str, **kwargs):
|
|
93
|
+
"""Run connector test mode"""
|
|
94
|
+
kv_dtype_str = kwargs.get("kv_dtype") or DEFAULT_KV_DTYPE_STR
|
|
95
|
+
kv_dtype = parse_kv_dtype(kv_dtype_str)
|
|
96
|
+
if kv_dtype is None:
|
|
97
|
+
print("Error: unsupported --kv-dtype '%s'" % kv_dtype_str)
|
|
98
|
+
return
|
|
99
|
+
|
|
100
|
+
obj_size = kwargs.get("obj_size")
|
|
101
|
+
|
|
102
|
+
config = lmcache_get_or_create_config()
|
|
103
|
+
metadata = _get_default_metadata(model, kv_dtype=kv_dtype, obj_size=obj_size)
|
|
104
|
+
|
|
105
|
+
# Create and start event loop manager
|
|
106
|
+
loop_manager = EventLoopManager()
|
|
107
|
+
loop_manager.start()
|
|
108
|
+
|
|
109
|
+
local_cpu_backend = LocalCPUBackend(
|
|
110
|
+
config=config, metadata=metadata, dst_device="cpu"
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
backend = RemoteBackend(
|
|
114
|
+
config=config,
|
|
115
|
+
metadata=metadata,
|
|
116
|
+
loop=loop_manager.get_loop(),
|
|
117
|
+
local_cpu_backend=local_cpu_backend,
|
|
118
|
+
dst_device="cpu",
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
# Create test context for the common framework
|
|
123
|
+
test_context = {
|
|
124
|
+
"create_test_data_func": create_test_data_for_backend,
|
|
125
|
+
"async_contains_func": async_contains_backend,
|
|
126
|
+
"async_put_func": async_submit_put_backend,
|
|
127
|
+
"async_get_func": async_get_backend,
|
|
128
|
+
"validate_get_func": validate_get_results,
|
|
129
|
+
"test_object": backend,
|
|
130
|
+
"extra_args": [
|
|
131
|
+
local_cpu_backend,
|
|
132
|
+
],
|
|
133
|
+
"kv_dtype": kv_dtype,
|
|
134
|
+
"obj_size": obj_size,
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
# Run the common test framework
|
|
138
|
+
num_tests = kwargs.get("num_keys", 5)
|
|
139
|
+
settle_time = kwargs.get("settle_time", 0.0)
|
|
140
|
+
await run_common_test_framework(
|
|
141
|
+
test_context, model, num_tests=num_tests, settle_time=settle_time
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
except Exception as e:
|
|
145
|
+
print(f"Test Failed - Error: {e}")
|
|
146
|
+
finally:
|
|
147
|
+
# Clean up
|
|
148
|
+
try:
|
|
149
|
+
if backend:
|
|
150
|
+
backend.close()
|
|
151
|
+
except Exception as e:
|
|
152
|
+
print(f"Error closing backend: {e}")
|
|
153
|
+
|
|
154
|
+
# Stop the event loop
|
|
155
|
+
loop_manager.stop()
|