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,639 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Optional, Union
|
|
5
|
+
import asyncio
|
|
6
|
+
import threading
|
|
7
|
+
import time
|
|
8
|
+
import uuid
|
|
9
|
+
|
|
10
|
+
# Third Party
|
|
11
|
+
import msgspec
|
|
12
|
+
import zmq
|
|
13
|
+
|
|
14
|
+
# First Party
|
|
15
|
+
from lmcache.logging import init_logger
|
|
16
|
+
from lmcache.v1.memory_management import (
|
|
17
|
+
MemoryObj,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
# Third Party
|
|
22
|
+
from nixl._api import NixlAgent
|
|
23
|
+
|
|
24
|
+
# First Party
|
|
25
|
+
from lmcache.v1.rpc_utils import get_zmq_context, get_zmq_socket
|
|
26
|
+
from lmcache.v1.transfer_channel.abstract import BaseTransferChannel
|
|
27
|
+
from lmcache.v1.transfer_channel.transfer_utils import (
|
|
28
|
+
InitSideMsgBase,
|
|
29
|
+
InitSideRetMsgBase,
|
|
30
|
+
SideMsg,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
logger = init_logger(__name__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class NixlMsgBase(msgspec.Struct, tag=True):
|
|
37
|
+
"""Base class for all nixl-related messages"""
|
|
38
|
+
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class NixlInitRequest(NixlMsgBase):
|
|
43
|
+
local_meta_bytes: bytes # Metadata from the sender nixl agent
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class NixlMemRegRequest(NixlMsgBase):
|
|
47
|
+
remote_agent_name: bytes
|
|
48
|
+
local_id: str
|
|
49
|
+
local_xfer_dlist_bytes: bytes
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class NixlInitResponse(NixlMsgBase):
|
|
53
|
+
remote_agent_name: bytes
|
|
54
|
+
remote_meta_bytes: bytes # Metadata from the receiver nixl agent
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class NixlMemRegResponse(NixlMsgBase):
|
|
58
|
+
remote_xfer_dlist_bytes: bytes # Serialized transfer descriptors for the receiver
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
NixlMsg = Union[
|
|
62
|
+
NixlInitRequest, NixlInitResponse, NixlMemRegRequest, NixlMemRegResponse
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class NixlChannel(BaseTransferChannel):
|
|
67
|
+
def __init__(
|
|
68
|
+
self,
|
|
69
|
+
async_mode: bool = False,
|
|
70
|
+
device: Optional[str] = None,
|
|
71
|
+
**kwargs,
|
|
72
|
+
):
|
|
73
|
+
assert "role" in kwargs
|
|
74
|
+
assert "buffer_ptr" in kwargs
|
|
75
|
+
assert "buffer_size" in kwargs
|
|
76
|
+
assert "align_bytes" in kwargs
|
|
77
|
+
assert "tp_rank" in kwargs
|
|
78
|
+
assert "peer_init_url" in kwargs
|
|
79
|
+
|
|
80
|
+
if "backends" in kwargs:
|
|
81
|
+
backends = kwargs["backends"]
|
|
82
|
+
else:
|
|
83
|
+
backends = ["UCX"]
|
|
84
|
+
|
|
85
|
+
self.role = kwargs["role"]
|
|
86
|
+
|
|
87
|
+
self.nixl_wrapper = NixlAgentWrapper(
|
|
88
|
+
buffer_ptr=kwargs["buffer_ptr"],
|
|
89
|
+
buffer_size=kwargs["buffer_size"],
|
|
90
|
+
page_size=kwargs["align_bytes"],
|
|
91
|
+
tp_rank=kwargs["tp_rank"],
|
|
92
|
+
backends=backends,
|
|
93
|
+
device=device,
|
|
94
|
+
)
|
|
95
|
+
self.nixl_agent = self.nixl_wrapper.agent
|
|
96
|
+
|
|
97
|
+
# Used for P2P
|
|
98
|
+
self.peer_lookup_url = kwargs.get("peer_lookup_url", None)
|
|
99
|
+
|
|
100
|
+
self.running = True
|
|
101
|
+
self.remote_xfer_handlers_dict: dict[
|
|
102
|
+
str, NixlAgent.nixl_prepped_dlist_handle
|
|
103
|
+
] = {}
|
|
104
|
+
|
|
105
|
+
self.side_channels: list[zmq.Socket] = []
|
|
106
|
+
self.running_threads: list[threading.Thread] = []
|
|
107
|
+
|
|
108
|
+
self.async_mode = async_mode
|
|
109
|
+
if self.async_mode:
|
|
110
|
+
self.zmq_context = get_zmq_context(use_asyncio=True)
|
|
111
|
+
else:
|
|
112
|
+
self.zmq_context = get_zmq_context(use_asyncio=False)
|
|
113
|
+
self.peer_init_url = kwargs["peer_init_url"]
|
|
114
|
+
self.event_loop = kwargs.get("event_loop", None)
|
|
115
|
+
|
|
116
|
+
self._init_side_channels()
|
|
117
|
+
|
|
118
|
+
############################################################
|
|
119
|
+
# Initialization functions
|
|
120
|
+
############################################################
|
|
121
|
+
def lazy_init_peer_connection(
|
|
122
|
+
self,
|
|
123
|
+
local_id: str,
|
|
124
|
+
peer_id: str,
|
|
125
|
+
peer_init_url: str,
|
|
126
|
+
init_side_msg: Optional[InitSideMsgBase] = None,
|
|
127
|
+
) -> Optional[InitSideRetMsgBase]:
|
|
128
|
+
# Initialize temporary socket for nixl initialization
|
|
129
|
+
init_tmp_socket = get_zmq_socket(
|
|
130
|
+
self.zmq_context,
|
|
131
|
+
peer_init_url,
|
|
132
|
+
"tcp",
|
|
133
|
+
zmq.REQ,
|
|
134
|
+
"connect",
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Build and send init request
|
|
138
|
+
nixl_init_req = NixlInitRequest(
|
|
139
|
+
local_meta_bytes=self.nixl_agent.get_agent_metadata(),
|
|
140
|
+
)
|
|
141
|
+
init_tmp_socket.send(msgspec.msgpack.encode(nixl_init_req))
|
|
142
|
+
|
|
143
|
+
# Wait remote agent metadata and register remote agent
|
|
144
|
+
nixl_init_resp_bytes = init_tmp_socket.recv()
|
|
145
|
+
nixl_init_resp = msgspec.msgpack.decode(nixl_init_resp_bytes, type=NixlMsg)
|
|
146
|
+
remote_meta_bytes = nixl_init_resp.remote_meta_bytes
|
|
147
|
+
remote_agent_name = self.nixl_agent.add_remote_agent(remote_meta_bytes)
|
|
148
|
+
|
|
149
|
+
# Register remote memory
|
|
150
|
+
local_xfer_dlist_bytes = self.nixl_agent.get_serialized_descs(
|
|
151
|
+
self.nixl_wrapper.xfer_descs
|
|
152
|
+
)
|
|
153
|
+
nixl_mem_reg_req = NixlMemRegRequest(
|
|
154
|
+
remote_agent_name=nixl_init_resp.remote_agent_name,
|
|
155
|
+
local_id=local_id,
|
|
156
|
+
local_xfer_dlist_bytes=local_xfer_dlist_bytes,
|
|
157
|
+
)
|
|
158
|
+
init_tmp_socket.send(msgspec.msgpack.encode(nixl_mem_reg_req))
|
|
159
|
+
nixl_mem_reg_resp_bytes = init_tmp_socket.recv()
|
|
160
|
+
nixl_mem_reg_resp = msgspec.msgpack.decode(
|
|
161
|
+
nixl_mem_reg_resp_bytes, type=NixlMsg
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
remote_xfer_dlist_bytes = nixl_mem_reg_resp.remote_xfer_dlist_bytes
|
|
165
|
+
remote_xfer_dlist = self.nixl_agent.deserialize_descs(remote_xfer_dlist_bytes)
|
|
166
|
+
remote_xfer_handlers = self.nixl_agent.prep_xfer_dlist(
|
|
167
|
+
remote_agent_name, remote_xfer_dlist
|
|
168
|
+
)
|
|
169
|
+
self.remote_xfer_handlers_dict[peer_id] = remote_xfer_handlers
|
|
170
|
+
|
|
171
|
+
# Send side message if any
|
|
172
|
+
init_ret_msg: Optional[InitSideRetMsgBase] = None
|
|
173
|
+
if init_side_msg is not None:
|
|
174
|
+
init_ret_msg = self.send_init_side_msg(
|
|
175
|
+
init_tmp_socket,
|
|
176
|
+
init_side_msg,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
init_tmp_socket.close()
|
|
180
|
+
return init_ret_msg
|
|
181
|
+
|
|
182
|
+
async def async_lazy_init_peer_connection(
|
|
183
|
+
self,
|
|
184
|
+
local_id: str,
|
|
185
|
+
peer_id: str,
|
|
186
|
+
peer_init_url: str,
|
|
187
|
+
init_side_msg: Optional[InitSideMsgBase] = None,
|
|
188
|
+
) -> Optional[InitSideRetMsgBase]:
|
|
189
|
+
# Initialize temporary socket for nixl initialization
|
|
190
|
+
init_tmp_socket = get_zmq_socket(
|
|
191
|
+
self.zmq_context,
|
|
192
|
+
peer_init_url,
|
|
193
|
+
"tcp",
|
|
194
|
+
zmq.REQ,
|
|
195
|
+
"connect",
|
|
196
|
+
)
|
|
197
|
+
# Build and send init request
|
|
198
|
+
nixl_init_req = NixlInitRequest(
|
|
199
|
+
local_meta_bytes=self.nixl_agent.get_agent_metadata(),
|
|
200
|
+
)
|
|
201
|
+
await init_tmp_socket.send(msgspec.msgpack.encode(nixl_init_req))
|
|
202
|
+
# Wait remote agent metadata and register remote agent
|
|
203
|
+
nixl_init_resp_bytes = await init_tmp_socket.recv()
|
|
204
|
+
nixl_init_resp = msgspec.msgpack.decode(nixl_init_resp_bytes, type=NixlMsg)
|
|
205
|
+
remote_meta_bytes = nixl_init_resp.remote_meta_bytes
|
|
206
|
+
remote_agent_name = self.nixl_agent.add_remote_agent(remote_meta_bytes)
|
|
207
|
+
|
|
208
|
+
# Register remote memory
|
|
209
|
+
local_xfer_dlist_bytes = self.nixl_agent.get_serialized_descs(
|
|
210
|
+
self.nixl_wrapper.xfer_descs
|
|
211
|
+
)
|
|
212
|
+
nixl_mem_reg_req = NixlMemRegRequest(
|
|
213
|
+
remote_agent_name=nixl_init_resp.remote_agent_name,
|
|
214
|
+
local_id=local_id,
|
|
215
|
+
local_xfer_dlist_bytes=local_xfer_dlist_bytes,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
await init_tmp_socket.send(msgspec.msgpack.encode(nixl_mem_reg_req))
|
|
219
|
+
nixl_mem_reg_resp_bytes = await init_tmp_socket.recv()
|
|
220
|
+
nixl_mem_reg_resp = msgspec.msgpack.decode(
|
|
221
|
+
nixl_mem_reg_resp_bytes, type=NixlMsg
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
remote_xfer_dlist_bytes = nixl_mem_reg_resp.remote_xfer_dlist_bytes
|
|
225
|
+
remote_xfer_dlist = self.nixl_agent.deserialize_descs(remote_xfer_dlist_bytes)
|
|
226
|
+
remote_xfer_handlers = self.nixl_agent.prep_xfer_dlist(
|
|
227
|
+
remote_agent_name, remote_xfer_dlist
|
|
228
|
+
)
|
|
229
|
+
self.remote_xfer_handlers_dict[peer_id] = remote_xfer_handlers
|
|
230
|
+
|
|
231
|
+
# Send side message if any
|
|
232
|
+
init_ret_msg: Optional[InitSideRetMsgBase] = None
|
|
233
|
+
if init_side_msg is not None:
|
|
234
|
+
init_ret_msg = await self.async_send_init_side_msg(
|
|
235
|
+
init_tmp_socket,
|
|
236
|
+
init_side_msg,
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
init_tmp_socket.close()
|
|
240
|
+
return init_ret_msg
|
|
241
|
+
|
|
242
|
+
def remote_xfer_handler_exists(self, receiver_or_sender_id: str) -> bool:
|
|
243
|
+
return receiver_or_sender_id in self.remote_xfer_handlers_dict
|
|
244
|
+
|
|
245
|
+
def _init_side_channels(self):
|
|
246
|
+
if self.peer_init_url is None:
|
|
247
|
+
return
|
|
248
|
+
|
|
249
|
+
if self.async_mode:
|
|
250
|
+
# Start listening coroutine for initialization side channel
|
|
251
|
+
asyncio.run_coroutine_threadsafe(self._async_init_loop(), self.event_loop)
|
|
252
|
+
else:
|
|
253
|
+
# Start listening thread for initialization side channel
|
|
254
|
+
self.init_thread = threading.Thread(target=self._init_loop, daemon=True)
|
|
255
|
+
self.init_thread.start()
|
|
256
|
+
self.running_threads.append(self.init_thread)
|
|
257
|
+
|
|
258
|
+
def _handle_init_msg(
|
|
259
|
+
self, req: Union[NixlMsg, InitSideMsgBase]
|
|
260
|
+
) -> Union[NixlMsg, InitSideRetMsgBase]:
|
|
261
|
+
resp: Union[NixlMsg, InitSideRetMsgBase]
|
|
262
|
+
if isinstance(req, NixlInitRequest):
|
|
263
|
+
agent_name = self.nixl_agent.add_remote_agent(req.local_meta_bytes)
|
|
264
|
+
|
|
265
|
+
resp = NixlInitResponse(
|
|
266
|
+
remote_agent_name=agent_name,
|
|
267
|
+
remote_meta_bytes=self.nixl_agent.get_agent_metadata(),
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
logger.info("Replying initialization response")
|
|
271
|
+
|
|
272
|
+
elif isinstance(req, NixlMemRegRequest):
|
|
273
|
+
local_xfer_descs = self.nixl_agent.get_serialized_descs(
|
|
274
|
+
self.nixl_wrapper.xfer_descs
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
remote_xfer_dlist_bytes = req.local_xfer_dlist_bytes
|
|
278
|
+
remote_xfer_dlist = self.nixl_agent.deserialize_descs(
|
|
279
|
+
remote_xfer_dlist_bytes
|
|
280
|
+
)
|
|
281
|
+
remote_xfer_handlers = self.nixl_agent.prep_xfer_dlist(
|
|
282
|
+
req.remote_agent_name, remote_xfer_dlist
|
|
283
|
+
)
|
|
284
|
+
self.remote_xfer_handlers_dict[req.local_id] = remote_xfer_handlers
|
|
285
|
+
|
|
286
|
+
resp = NixlMemRegResponse(
|
|
287
|
+
remote_xfer_dlist_bytes=local_xfer_descs,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
logger.info("Replying mem register response")
|
|
291
|
+
elif isinstance(req, InitSideMsgBase):
|
|
292
|
+
resp = self.handle_init_side_msg(req)
|
|
293
|
+
logger.info("Replying P2P init side response")
|
|
294
|
+
else:
|
|
295
|
+
raise ValueError(f"Unsupported InitMsg type: {type(req)}")
|
|
296
|
+
|
|
297
|
+
return resp
|
|
298
|
+
|
|
299
|
+
def _init_loop(self):
|
|
300
|
+
# Initialize initialization side channels
|
|
301
|
+
self.init_side_channel = get_zmq_socket(
|
|
302
|
+
self.zmq_context,
|
|
303
|
+
self.peer_init_url,
|
|
304
|
+
"tcp",
|
|
305
|
+
zmq.REP,
|
|
306
|
+
"bind",
|
|
307
|
+
)
|
|
308
|
+
self.side_channels.append(self.init_side_channel)
|
|
309
|
+
|
|
310
|
+
# NOTE: Initialization has to be two stages:
|
|
311
|
+
# (1) Exchanging the metadata.
|
|
312
|
+
# (2) Registering the memory descriptors.
|
|
313
|
+
# Otherwise, there's a chance that nixl got stuck
|
|
314
|
+
# (handle always give "PROC" status) during the first request.
|
|
315
|
+
# (3) Exchanging side messages if any. This depends on the backend
|
|
316
|
+
# that uses the channel.
|
|
317
|
+
while self.running:
|
|
318
|
+
try:
|
|
319
|
+
req_bytes = self.init_side_channel.recv()
|
|
320
|
+
|
|
321
|
+
logger.info("Received initialization request")
|
|
322
|
+
|
|
323
|
+
req = msgspec.msgpack.decode(req_bytes, type=Union[NixlMsg, SideMsg])
|
|
324
|
+
|
|
325
|
+
resp = self._handle_init_msg(req)
|
|
326
|
+
|
|
327
|
+
self.init_side_channel.send(msgspec.msgpack.encode(resp))
|
|
328
|
+
|
|
329
|
+
except Exception as e:
|
|
330
|
+
logger.error("Failed to process initialization loop: %s", str(e))
|
|
331
|
+
if self.running:
|
|
332
|
+
time.sleep(0.01)
|
|
333
|
+
|
|
334
|
+
async def _async_init_loop(self):
|
|
335
|
+
# Initialize initialization side channels
|
|
336
|
+
self.init_side_channel = get_zmq_socket(
|
|
337
|
+
self.zmq_context,
|
|
338
|
+
self.peer_init_url,
|
|
339
|
+
"tcp",
|
|
340
|
+
zmq.REP,
|
|
341
|
+
"bind",
|
|
342
|
+
)
|
|
343
|
+
self.side_channels.append(self.init_side_channel)
|
|
344
|
+
logger.info("Starting async initialization loop")
|
|
345
|
+
|
|
346
|
+
while self.running:
|
|
347
|
+
try:
|
|
348
|
+
req_bytes = await self.init_side_channel.recv()
|
|
349
|
+
|
|
350
|
+
logger.info("Received initialization request")
|
|
351
|
+
|
|
352
|
+
req = msgspec.msgpack.decode(req_bytes, type=Union[NixlMsg, SideMsg])
|
|
353
|
+
|
|
354
|
+
resp = self._handle_init_msg(req)
|
|
355
|
+
|
|
356
|
+
await self.init_side_channel.send(msgspec.msgpack.encode(resp))
|
|
357
|
+
|
|
358
|
+
except Exception as e:
|
|
359
|
+
logger.error("Failed to process initialization loop: %s", str(e))
|
|
360
|
+
if self.running:
|
|
361
|
+
time.sleep(0.01)
|
|
362
|
+
|
|
363
|
+
############################################################
|
|
364
|
+
# Utility functions
|
|
365
|
+
############################################################
|
|
366
|
+
|
|
367
|
+
def get_local_mem_indices(
|
|
368
|
+
self, objects: Union[list[bytes], list[MemoryObj]]
|
|
369
|
+
) -> list[int]:
|
|
370
|
+
local_indices = []
|
|
371
|
+
if isinstance(objects[0], MemoryObj):
|
|
372
|
+
for mem_obj in objects:
|
|
373
|
+
assert isinstance(mem_obj, MemoryObj)
|
|
374
|
+
local_indices.append(mem_obj.meta.address)
|
|
375
|
+
elif isinstance(objects[0], bytes):
|
|
376
|
+
raise NotImplementedError(
|
|
377
|
+
"Sending raw bytes is not supported in NIXL channel"
|
|
378
|
+
)
|
|
379
|
+
return local_indices
|
|
380
|
+
|
|
381
|
+
############################################################
|
|
382
|
+
# Send/Recv functions
|
|
383
|
+
############################################################
|
|
384
|
+
|
|
385
|
+
### Send and Recv must be called in pair ###
|
|
386
|
+
def batched_send(
|
|
387
|
+
self,
|
|
388
|
+
objects: Union[list[bytes], list[MemoryObj]],
|
|
389
|
+
transfer_spec: Optional[dict] = None,
|
|
390
|
+
) -> int:
|
|
391
|
+
raise NotImplementedError
|
|
392
|
+
|
|
393
|
+
def batched_recv(
|
|
394
|
+
self,
|
|
395
|
+
buffers: Union[list[bytes], list[MemoryObj]],
|
|
396
|
+
transfer_spec: Optional[dict] = None,
|
|
397
|
+
) -> int:
|
|
398
|
+
raise NotImplementedError
|
|
399
|
+
|
|
400
|
+
async def async_batched_send(
|
|
401
|
+
self,
|
|
402
|
+
objects: Union[list[bytes], list[MemoryObj]],
|
|
403
|
+
transfer_spec: Optional[dict] = None,
|
|
404
|
+
) -> int:
|
|
405
|
+
raise NotImplementedError
|
|
406
|
+
|
|
407
|
+
async def async_batched_recv(
|
|
408
|
+
self,
|
|
409
|
+
buffers: Union[list[bytes], list[MemoryObj]],
|
|
410
|
+
transfer_spec: Optional[dict] = None,
|
|
411
|
+
) -> int:
|
|
412
|
+
raise NotImplementedError
|
|
413
|
+
|
|
414
|
+
############################################################
|
|
415
|
+
# Read/Write functions
|
|
416
|
+
############################################################
|
|
417
|
+
|
|
418
|
+
### Read and Write only need to be called on one side ###
|
|
419
|
+
def batched_write(
|
|
420
|
+
self,
|
|
421
|
+
objects: Union[list[bytes], list[MemoryObj]],
|
|
422
|
+
transfer_spec: Optional[dict] = None,
|
|
423
|
+
) -> int:
|
|
424
|
+
"""
|
|
425
|
+
Write a batch of data through the nixl channel.
|
|
426
|
+
|
|
427
|
+
:param objects: A list of bytes or MemoryObj to be written.
|
|
428
|
+
:param transfer_spec: Additional specifications for the transfer.
|
|
429
|
+
|
|
430
|
+
:return: Number of successfully transferred objects.
|
|
431
|
+
"""
|
|
432
|
+
assert transfer_spec is not None
|
|
433
|
+
|
|
434
|
+
handle = self.nixl_agent.make_prepped_xfer(
|
|
435
|
+
"WRITE",
|
|
436
|
+
self.nixl_wrapper.xfer_handler,
|
|
437
|
+
self.get_local_mem_indices(objects),
|
|
438
|
+
self.remote_xfer_handlers_dict[transfer_spec["receiver_id"]],
|
|
439
|
+
transfer_spec["remote_indexes"],
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
self.nixl_agent.transfer(handle)
|
|
443
|
+
|
|
444
|
+
# TODO(Jiayi) tune hyperparameters
|
|
445
|
+
wait_time = 0.001
|
|
446
|
+
while True:
|
|
447
|
+
status = self.nixl_agent.check_xfer_state(handle)
|
|
448
|
+
logger.debug(f"Transfer status: {status}")
|
|
449
|
+
|
|
450
|
+
if status == "ERR":
|
|
451
|
+
logger.error("Error in send operation")
|
|
452
|
+
raise RuntimeError("Failed to send objects to remote peer")
|
|
453
|
+
elif status == "PROC":
|
|
454
|
+
time.sleep(wait_time) # Avoid busy waiting
|
|
455
|
+
continue
|
|
456
|
+
assert status == "DONE", f"Transfer status is {status}, expected DONE"
|
|
457
|
+
# self._proxy_side_channel.send(notif_msg_bytes)
|
|
458
|
+
break
|
|
459
|
+
|
|
460
|
+
return len(objects)
|
|
461
|
+
|
|
462
|
+
def batched_read(
|
|
463
|
+
self,
|
|
464
|
+
buffers: Union[list[bytes], list[MemoryObj]],
|
|
465
|
+
transfer_spec: Optional[dict] = None,
|
|
466
|
+
) -> int:
|
|
467
|
+
raise NotImplementedError
|
|
468
|
+
|
|
469
|
+
async def async_batched_write(
|
|
470
|
+
self,
|
|
471
|
+
objects: Union[list[bytes], list[MemoryObj]],
|
|
472
|
+
transfer_spec: Optional[dict] = None,
|
|
473
|
+
) -> int:
|
|
474
|
+
"""
|
|
475
|
+
Write a batch of data through the channel.
|
|
476
|
+
|
|
477
|
+
:param objects: A list of bytes or MemoryObj to be written.
|
|
478
|
+
:param transfer_spec: Additional specifications for the transfer.
|
|
479
|
+
Should contain 'receiver_id' and 'remote_indexes'.
|
|
480
|
+
|
|
481
|
+
:return: Number of successfully transferred objects.
|
|
482
|
+
"""
|
|
483
|
+
|
|
484
|
+
assert transfer_spec is not None
|
|
485
|
+
|
|
486
|
+
handle = self.nixl_agent.make_prepped_xfer(
|
|
487
|
+
"WRITE",
|
|
488
|
+
self.nixl_wrapper.xfer_handler,
|
|
489
|
+
self.get_local_mem_indices(objects),
|
|
490
|
+
self.remote_xfer_handlers_dict[transfer_spec["receiver_id"]],
|
|
491
|
+
transfer_spec["remote_indexes"],
|
|
492
|
+
)
|
|
493
|
+
self.nixl_agent.transfer(handle)
|
|
494
|
+
|
|
495
|
+
# TODO(Jiayi) tune hyperparameters
|
|
496
|
+
wait_time = 0.001
|
|
497
|
+
while True:
|
|
498
|
+
status = self.nixl_agent.check_xfer_state(handle)
|
|
499
|
+
logger.debug(f"Transfer status: {status}")
|
|
500
|
+
|
|
501
|
+
if status == "ERR":
|
|
502
|
+
logger.error("Error in send operation")
|
|
503
|
+
raise RuntimeError("Failed to send objects to remote peer")
|
|
504
|
+
elif status == "PROC":
|
|
505
|
+
await asyncio.sleep(wait_time) # Avoid busy waiting
|
|
506
|
+
continue
|
|
507
|
+
assert status == "DONE", f"Transfer status is {status}, expected DONE"
|
|
508
|
+
# self._proxy_side_channel.send(notif_msg_bytes)
|
|
509
|
+
break
|
|
510
|
+
return len(objects)
|
|
511
|
+
|
|
512
|
+
async def async_batched_read(
|
|
513
|
+
self,
|
|
514
|
+
buffers: Union[list[bytes], list[MemoryObj]],
|
|
515
|
+
transfer_spec: Optional[dict] = None,
|
|
516
|
+
) -> int:
|
|
517
|
+
"""
|
|
518
|
+
Read a batch of data through the channel.
|
|
519
|
+
|
|
520
|
+
:param buffers: A list of bytes or MemoryObj to store the read data.
|
|
521
|
+
:param transfer_spec: Additional specifications for the transfer.
|
|
522
|
+
|
|
523
|
+
:return: True if the send operation is successful.
|
|
524
|
+
"""
|
|
525
|
+
|
|
526
|
+
assert transfer_spec is not None
|
|
527
|
+
|
|
528
|
+
handle = self.nixl_agent.make_prepped_xfer(
|
|
529
|
+
"READ",
|
|
530
|
+
self.nixl_wrapper.xfer_handler,
|
|
531
|
+
self.get_local_mem_indices(buffers),
|
|
532
|
+
self.remote_xfer_handlers_dict[transfer_spec["sender_id"]],
|
|
533
|
+
transfer_spec["remote_indexes"],
|
|
534
|
+
)
|
|
535
|
+
self.nixl_agent.transfer(handle)
|
|
536
|
+
|
|
537
|
+
# TODO(Jiayi) tune hyperparameters
|
|
538
|
+
wait_time = 0.001
|
|
539
|
+
while True:
|
|
540
|
+
status = self.nixl_agent.check_xfer_state(handle)
|
|
541
|
+
logger.debug(f"Transfer status: {status}")
|
|
542
|
+
|
|
543
|
+
if status == "ERR":
|
|
544
|
+
logger.error("Error in send operation")
|
|
545
|
+
raise RuntimeError("Failed to send objects to remote peer")
|
|
546
|
+
elif status == "PROC":
|
|
547
|
+
await asyncio.sleep(wait_time) # Avoid busy waiting
|
|
548
|
+
continue
|
|
549
|
+
assert status == "DONE", f"Transfer status is {status}, expected DONE"
|
|
550
|
+
# self._proxy_side_channel.send(notif_msg_bytes)
|
|
551
|
+
break
|
|
552
|
+
return len(buffers)
|
|
553
|
+
|
|
554
|
+
############################################################
|
|
555
|
+
# Cleanup-related functions
|
|
556
|
+
############################################################
|
|
557
|
+
|
|
558
|
+
def close(self):
|
|
559
|
+
self.running = False
|
|
560
|
+
for thread in self.running_threads:
|
|
561
|
+
thread.join()
|
|
562
|
+
self.zmq_context.term()
|
|
563
|
+
self.nixl_agent.deregister_memory(self.nixl_wrapper.reg_descs)
|
|
564
|
+
self.nixl_agent.release_dlist_handle(self.nixl_wrapper.xfer_handler)
|
|
565
|
+
|
|
566
|
+
for remote_xfer_handler in self.remote_xfer_handlers_dict.values():
|
|
567
|
+
self.nixl_agent.release_dlist_handle(remote_xfer_handler)
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
@dataclass
|
|
571
|
+
class NixlAgentWrapper:
|
|
572
|
+
agent: "NixlAgent"
|
|
573
|
+
reg_descs: Any
|
|
574
|
+
xfer_descs: Any
|
|
575
|
+
xfer_handler: Any
|
|
576
|
+
|
|
577
|
+
def __init__(
|
|
578
|
+
self,
|
|
579
|
+
buffer_ptr: int,
|
|
580
|
+
buffer_size: int,
|
|
581
|
+
page_size: int,
|
|
582
|
+
tp_rank: int,
|
|
583
|
+
backends: list[str],
|
|
584
|
+
device: Optional[str] = None,
|
|
585
|
+
):
|
|
586
|
+
"""
|
|
587
|
+
Initialize the NIXL agent.
|
|
588
|
+
|
|
589
|
+
Args:
|
|
590
|
+
buffer_size (int): The size of the buffer.
|
|
591
|
+
buffer_ptr (int): The pointer to the buffer.
|
|
592
|
+
page_size (int): The page size of NIXL and
|
|
593
|
+
the lmcache memory allocator.
|
|
594
|
+
tp_rank (int): The tensor parallel rank.
|
|
595
|
+
backends (list[str]): The list of backends to use.
|
|
596
|
+
|
|
597
|
+
Returns:
|
|
598
|
+
NixlWrapper: The NIXL agent.
|
|
599
|
+
reg_dlist: the registered memory descriptor list.
|
|
600
|
+
xfer_dlist: the local transfer descriptor list.
|
|
601
|
+
prepped_xfer_handler: the prepped transfer handler.
|
|
602
|
+
"""
|
|
603
|
+
try:
|
|
604
|
+
# Third Party
|
|
605
|
+
from nixl._api import nixl_agent as NixlAgent
|
|
606
|
+
from nixl._api import nixl_agent_config
|
|
607
|
+
except ImportError as err:
|
|
608
|
+
raise RuntimeError("NIXL is not available") from err
|
|
609
|
+
|
|
610
|
+
# Handle None backends by setting default to ["UCX"]
|
|
611
|
+
if backends is None:
|
|
612
|
+
backends = ["UCX"]
|
|
613
|
+
|
|
614
|
+
# Create a NIXL agent
|
|
615
|
+
nixl_agent = NixlAgent(
|
|
616
|
+
str(uuid.uuid4()),
|
|
617
|
+
nixl_agent_config(backends=backends),
|
|
618
|
+
)
|
|
619
|
+
|
|
620
|
+
# Register the memory
|
|
621
|
+
# The four fields are (base_addr, length, dev_id, meta_info)
|
|
622
|
+
# https://github.com/ai-dynamo/nixl/blob/main/src/api/cpp/nixl_descriptors.h#L152
|
|
623
|
+
memory_desc = [(buffer_ptr, buffer_size, tp_rank, "")]
|
|
624
|
+
mem_type = "cpu" if device == "cpu" else "cuda"
|
|
625
|
+
|
|
626
|
+
reg_descs = nixl_agent.get_reg_descs(memory_desc, mem_type=mem_type)
|
|
627
|
+
nixl_agent.register_memory(reg_descs)
|
|
628
|
+
|
|
629
|
+
# Create xfer handlers
|
|
630
|
+
xfer_desc = []
|
|
631
|
+
for base_addr in range(buffer_ptr, buffer_ptr + buffer_size, page_size):
|
|
632
|
+
xfer_desc.append((base_addr, page_size, tp_rank))
|
|
633
|
+
|
|
634
|
+
xfer_descs = nixl_agent.get_xfer_descs(xfer_desc, mem_type=mem_type)
|
|
635
|
+
xfer_handler = nixl_agent.prep_xfer_dlist("", xfer_descs, mem_type=mem_type)
|
|
636
|
+
self.agent = nixl_agent
|
|
637
|
+
self.reg_descs = reg_descs
|
|
638
|
+
self.xfer_descs = xfer_descs
|
|
639
|
+
self.xfer_handler = xfer_handler
|