Files
lmcache--lmcache/csrc/pybind.cpp
T
2026-07-13 12:24:33 +08:00

182 lines
9.0 KiB
C++

// SPDX-License-Identifier: Apache-2.0
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "mem_kernels.cuh"
#include "mp_mem_kernels.cuh"
#include "cachegen_kernels.cuh"
#include "pos_kernels.cuh"
#include "mem_alloc.h"
#include "utils.h"
#include "event_recorder.h"
#include "completion_recorder.h"
#include <torch/torch.h>
#include <torch/extension.h>
#include <iostream>
namespace py = pybind11;
PYBIND11_MODULE(c_ops, m) {
py::enum_<TransferDirection>(m, "TransferDirection")
.value("H2D", TransferDirection::H2D)
.value("D2H", TransferDirection::D2H)
.export_values();
py::enum_<EngineKVFormat>(m, "EngineKVFormat")
.value("NB_NL_TWO_BS_NH_HS", EngineKVFormat::NB_NL_TWO_BS_NH_HS)
.value("NL_X_TWO_NB_BS_NH_HS", EngineKVFormat::NL_X_TWO_NB_BS_NH_HS)
.value("NL_X_NB_TWO_BS_NH_HS", EngineKVFormat::NL_X_NB_TWO_BS_NH_HS)
.value("NL_X_NB_BS_HS", EngineKVFormat::NL_X_NB_BS_HS)
.value("TWO_X_NL_X_NBBS_NH_HS", EngineKVFormat::TWO_X_NL_X_NBBS_NH_HS)
.value("NL_X_NBBS_ONE_HS", EngineKVFormat::NL_X_NBBS_ONE_HS)
.value("NL_X_TWO_NB_NH_BS_HS", EngineKVFormat::NL_X_TWO_NB_NH_BS_HS)
.value("NL_X_NB_TWO_NH_BS_HS", EngineKVFormat::NL_X_NB_TWO_NH_BS_HS)
.value("NB_NL_TWO_NH_BS_HS", EngineKVFormat::NB_NL_TWO_NH_BS_HS)
.value("TWO_X_NL_X_NB_BS_NH_HS", EngineKVFormat::TWO_X_NL_X_NB_BS_NH_HS)
.value("NL_X_NB_NH_BS_TWO_HS", EngineKVFormat::NL_X_NB_NH_BS_TWO_HS)
.export_values();
// Format classification, shared with the device kernels (engine_kv_format.h).
m.def(
"is_cross_layer", [](EngineKVFormat f) { return is_cross_layer(f); },
py::arg("engine_kv_format"));
m.def(
"is_kv_list", [](EngineKVFormat f) { return is_kv_list(f); },
py::arg("engine_kv_format"));
m.def(
"is_layer_list", [](EngineKVFormat f) { return is_layer_list(f); },
py::arg("engine_kv_format"));
m.def(
"is_mla", [](EngineKVFormat f) { return is_mla(f); },
py::arg("engine_kv_format"));
m.def("multi_layer_kv_transfer", &multi_layer_kv_transfer,
py::arg("key_value"), py::arg("key_value_ptrs"),
py::arg("slot_mapping"), py::arg("paged_memory_device"),
py::arg("page_buffer_size"), py::arg("direction"),
py::arg("engine_kv_format"), py::arg("block_size") = 0,
py::arg("head_size") = 0, py::arg("skip_prefix_n_tokens") = 0,
py::call_guard<py::gil_scoped_release>());
m.def("multi_layer_kv_transfer_unilateral",
&multi_layer_kv_transfer_unilateral);
m.def("single_layer_kv_transfer", &single_layer_kv_transfer,
py::arg("lmc_key_value_cache"), py::arg("vllm_key_value_cache"),
py::arg("slot_mapping"), py::arg("direction"),
py::arg("engine_kv_format"), py::arg("token_major") = false);
m.def("single_layer_kv_transfer_sgl", &single_layer_kv_transfer_sgl,
py::arg("lmc_key_value_cache"), py::arg("sgl_key_cache"),
py::arg("sgl_value_cache"), py::arg("slot_mapping"),
py::arg("direction"), py::arg("token_major") = false);
m.def("load_and_reshape_flash", &load_and_reshape_flash);
m.def("reshape_and_cache_back_flash", &reshape_and_cache_back_flash);
m.def("lmcache_memcpy_async", &lmcache_memcpy_async,
py::call_guard<py::gil_scoped_release>());
m.def("encode_fast_new", &encode_cuda_new);
m.def("decode_fast_new", &decode_cuda_new);
m.def("decode_fast_prefsum", &decode_cuda_prefsum);
m.def("calculate_cdf", &calculate_cdf);
m.def("rotary_embedding_k_fused", &rotary_embedding_k_fused);
m.def("alloc_pinned_ptr", &alloc_pinned_ptr,
py::call_guard<py::gil_scoped_release>());
m.def("free_pinned_ptr", &free_pinned_ptr);
m.def("alloc_hugepage_pinned_ptr", &alloc_hugepage_pinned_ptr,
py::call_guard<py::gil_scoped_release>());
m.def("free_hugepage_pinned_ptr", &free_hugepage_pinned_ptr);
m.def("alloc_pinned_numa_ptr", &alloc_pinned_numa_ptr,
py::call_guard<py::gil_scoped_release>());
m.def("free_pinned_numa_ptr", &free_pinned_numa_ptr);
m.def("alloc_hugepage_pinned_numa_ptr", &alloc_hugepage_pinned_numa_ptr,
py::call_guard<py::gil_scoped_release>());
m.def("free_hugepage_pinned_numa_ptr", &free_hugepage_pinned_numa_ptr);
m.def("alloc_numa_ptr", &alloc_numa_ptr,
py::call_guard<py::gil_scoped_release>());
m.def("free_numa_ptr", &free_numa_ptr);
m.def("alloc_shm_pinned_ptr", &alloc_shm_pinned_ptr,
py::call_guard<py::gil_scoped_release>());
m.def("free_shm_pinned_ptr", &free_shm_pinned_ptr,
py::call_guard<py::gil_scoped_release>());
m.def("batched_memcpy", &batched_memcpy, py::arg("src_ptrs"),
py::arg("dst_ptrs"), py::arg("sizes"),
py::call_guard<py::gil_scoped_release>());
m.def("get_gpu_pci_bus_id", &get_gpu_pci_bus_id);
m.def("multi_layer_block_kv_transfer", &multi_layer_block_kv_transfer,
py::arg("paged_buffer_ptrs_tensor"), py::arg("lmcache_objects_ptrs"),
py::arg("block_ids"), py::arg("device"), py::arg("direction"),
py::arg("shape_desc"), py::arg("lmcache_chunk_size"),
py::arg("engine_kv_format"), py::arg("skip_prefix_n_blocks"),
py::call_guard<py::gil_scoped_release>());
py::class_<PageBufferShapeDesc>(m, "PageBufferShapeDesc")
.def(py::init<>())
.def_readwrite("kv_size", &PageBufferShapeDesc::kv_size)
.def_readwrite("nl", &PageBufferShapeDesc::nl)
.def_readwrite("nb", &PageBufferShapeDesc::nb)
.def_readwrite("bs", &PageBufferShapeDesc::bs)
.def_readwrite("nh", &PageBufferShapeDesc::nh)
.def_readwrite("hs", &PageBufferShapeDesc::hs)
.def_readwrite("element_size", &PageBufferShapeDesc::element_size)
.def_readwrite("block_stride_elems",
&PageBufferShapeDesc::block_stride_elems);
// Object-group transfer plan types (see mp_mem_kernels.cuh). Built on the
// Python side and consumed by execute_object_group_transfer.
py::class_<StagingCopy>(m, "StagingCopy")
.def(py::init([](uintptr_t dest, uintptr_t src, size_t nbytes,
size_t host_offset) {
return StagingCopy{dest, src, nbytes, host_offset};
}),
py::arg("dest"), py::arg("src"), py::arg("nbytes"),
py::arg("host_offset"));
py::class_<LaunchVar>(m, "LaunchVar")
.def(
py::init([](int group_idx, int64_t block_ids_offset, int total_blocks,
int num_objects, int skip_prefix_n_blocks) {
return LaunchVar{group_idx, block_ids_offset, total_blocks,
num_objects, skip_prefix_n_blocks};
}),
py::arg("group_idx"), py::arg("block_ids_offset"),
py::arg("total_blocks"), py::arg("num_objects"),
py::arg("skip_prefix_n_blocks"));
py::class_<BatchStep>(m, "BatchStep")
.def(py::init([](std::vector<StagingCopy> staging,
std::vector<LaunchVar> launches) {
return BatchStep{std::move(staging), std::move(launches)};
}),
py::arg("staging"), py::arg("launches"));
py::class_<KernelGroupSpec>(m, "KernelGroupSpec")
.def(py::init([](uintptr_t paged_buffer_ptrs,
std::vector<int64_t> lmcache_objects_ptrs,
PageBufferShapeDesc shape_desc, int lmcache_chunk_size,
EngineKVFormat engine_kv_format,
uintptr_t block_ids_base, int64_t block_ids_capacity) {
return KernelGroupSpec{
paged_buffer_ptrs, std::move(lmcache_objects_ptrs),
shape_desc, lmcache_chunk_size,
engine_kv_format, block_ids_base,
block_ids_capacity};
}),
py::arg("paged_buffer_ptrs"), py::arg("lmcache_objects_ptrs"),
py::arg("shape_desc"), py::arg("lmcache_chunk_size"),
py::arg("engine_kv_format"), py::arg("block_ids_base"),
py::arg("block_ids_capacity"));
m.def("execute_object_group_transfer", &execute_object_group_transfer,
py::arg("direction"), py::arg("device"),
py::arg("host_buffer_alignment"), py::arg("kernel_group_specs"),
py::arg("batch_steps"), py::call_guard<py::gil_scoped_release>());
m.def("record_event_on_stream", &record_event_on_stream,
py::arg("cuda_stream_ptr"), py::arg("event_type_name"),
py::arg("session_id"), py::arg("str_metadata"), py::arg("int_metadata"),
py::call_guard<py::gil_scoped_release>());
m.def("drain_recorded_events", &drain_recorded_events);
m.def("record_completion_on_stream", &record_completion_on_stream,
py::arg("cuda_stream_ptr"), py::arg("kind"), py::arg("payload"),
py::call_guard<py::gil_scoped_release>());
// Return each payload as py::bytes; pybind11 utf-8-decodes std::string
// by default, corrupting binary payloads (e.g. msgpack).
m.def("drain_recorded_completions", []() {
auto items = drain_recorded_completions();
py::list out;
for (auto& kv : items) {
out.append(py::make_tuple(py::str(kv.first), py::bytes(kv.second)));
}
return out;
});
// Backward-compat alias: GPUKVFormat -> EngineKVFormat
m.attr("GPUKVFormat") = m.attr("EngineKVFormat");
}