Skip to content

Commit bbeadd9

Browse files
uuzWYuuzWY
authored andcommitted
feat: add xlite as third npu backend (support qwen3-dense/qwen3-moe/glm-4.7/glm-5.1/glm-5.2)
1 parent 3906f5a commit bbeadd9

27 files changed

Lines changed: 2790 additions & 3 deletions

CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ option(USE_MUSA "Enable MUSA support" OFF)
99
option(USE_DCU "Enable DCU support" OFF)
1010
option(USE_MACA "Enable MACA support" OFF)
1111
option(ENABLE_HA "Enable Mooncake etcd-based high availability support" OFF)
12+
option(USE_XLITE "Enable xlite backend (NPU only)" OFF)
1213
add_compile_definitions(YLT_ENABLE_IBV)
1314
add_definitions(-DYLT_ENABLE_IBV)
1415
set(YLT_ENABLE_IBV ON)
@@ -477,6 +478,12 @@ if(USE_NPU)
477478
set(CMAKE_VERBOSE_MAKEFILE ON)
478479
add_definitions(-DTORCH_HIGHER_THAN_PTA6)
479480

481+
if (USE_XLITE)
482+
add_definitions(-DUSE_XLITE)
483+
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/xlite.cmake)
484+
message(STATUS "USE_XLITE is ON")
485+
endif()
486+
480487
# Use vcpkg header files as the first priority search directory,
481488
#-> because the scope of third-party software managed by vcpkg is used throughout the entire xllm.
482489
message(STATUS "VCPKG_INCLUDE_DIR = ${CMAKE_BINARY_DIR}/vcpkg_installed/${VCPKG_TARGET_TRIPLET}/include")

cmake/xlite.cmake

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# xlite link helper: find_package(xlite) when USE_NPU AND USE_XLITE are ON.
2+
3+
function(xllm_link_xlite target)
4+
if(NOT USE_NPU OR NOT USE_XLITE)
5+
return()
6+
endif()
7+
8+
if(NOT TARGET xlite::xlite)
9+
execute_process(
10+
COMMAND ${Python_EXECUTABLE} -c "import xlite; print(xlite.cmake_prefix_path)"
11+
OUTPUT_VARIABLE _XLITE_CMAKE_PREFIX
12+
OUTPUT_STRIP_TRAILING_WHITESPACE
13+
RESULT_VARIABLE _XLITE_IMPORT_RESULT)
14+
if(NOT _XLITE_IMPORT_RESULT EQUAL 0 OR _XLITE_CMAKE_PREFIX STREQUAL "")
15+
message(FATAL_ERROR "USE_XLITE is ON but xlite not found. Install xlite or pass -DUSE_XLITE=OFF.")
16+
endif()
17+
18+
find_package(xlite REQUIRED CONFIG PATHS "${_XLITE_CMAKE_PREFIX}" NO_DEFAULT_PATH)
19+
message(STATUS "xlite::xlite found via find_package (${_XLITE_CMAKE_PREFIX})")
20+
endif()
21+
22+
target_link_libraries(${target} PRIVATE xlite::xlite)
23+
endfunction()

xllm/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ if(USE_MUSA)
127127
)
128128
endif()
129129

130+
if (USE_NPU AND USE_XLITE)
131+
xllm_link_xlite(xllm)
132+
endif()
130133
# install xllm
131134
install(TARGETS xllm RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
132135

xllm/core/framework/model/causal_lm.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ namespace layer {
4949
struct AttentionMetadata;
5050
}
5151

52+
namespace xlite {
53+
class XliteModelHolder;
54+
}
55+
5256
struct ModelGraphMetadataState {
5357
virtual ~ModelGraphMetadataState() = default;
5458
};
@@ -151,6 +155,9 @@ class CausalLM : public torch::nn::Module {
151155
NOT_IMPLEMENTED();
152156
return false;
153157
}
158+
159+
// xlite runtime access, nullptr for non-xlite models.
160+
virtual xlite::XliteModelHolder* get_xlite_holder() { return nullptr; }
154161
#endif
155162

156163
virtual layer::LmHead get_lm_head() {
@@ -444,6 +451,14 @@ class CausalLMImpl : public CausalLM {
444451
requested_rolling_slots,
445452
model_id);
446453
}
454+
455+
// Forward to inner Model.
456+
xlite::XliteModelHolder* get_xlite_holder() override {
457+
if constexpr (detail::has_get_xlite_holder<Model>::value) {
458+
return model_->get_xlite_holder();
459+
}
460+
return CausalLM::get_xlite_holder();
461+
}
447462
#endif
448463

449464
layer::LmHead get_lm_head() override {

xllm/core/framework/model/model_traits.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,15 @@ struct has_init_or_refresh_rolling_runtime<
246246
std::declval<int32_t>(),
247247
std::declval<const std::string&>()))>> : std::true_type {};
248248

249+
// SFINAE: xlite-backend models expose get_xlite_holder().
250+
template <typename T, typename = void>
251+
struct has_get_xlite_holder : std::false_type {};
252+
253+
template <typename T>
254+
struct has_get_xlite_holder<
255+
T,
256+
std::void_t<decltype(std::declval<T>()->get_xlite_holder())>>
257+
: std::true_type {};
249258
#endif
250259

251260
template <typename T, typename = void>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/* Copyright 2025-2026 The xLLM Authors.
2+
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
7+
https://github.com/jd-opensource/xllm/blob/main/LICENSE
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
==============================================================================*/
15+
16+
// Build xlite XModelAttnMeta from xllm ModelInputParams.
17+
18+
#pragma once
19+
20+
#include <xlite/xlite.h>
21+
22+
#include <algorithm>
23+
#include <cstdint>
24+
#include <vector>
25+
26+
#include "core/framework/model/model_input_params.h"
27+
#include "core/layers/xlite/xlite_init_utils.h"
28+
29+
namespace xllm::xlite {
30+
31+
class XliteAttnMetaBuilder {
32+
public:
33+
static void Build(const ModelInputParams& params,
34+
const torch::Tensor& positions,
35+
uint32_t block_size,
36+
XModelAttnMeta& m,
37+
int64_t pad_count = 0) {
38+
// version=0: xlite recomputes position from cachedLens (framework's
39+
// positions tensor is off-by-one on decode).
40+
m.version = 0;
41+
m.lens.clear();
42+
m.cachedLens.clear();
43+
m.blockTables.clear();
44+
45+
const auto& host = params.attention.host;
46+
int n = params.meta.num_sequences;
47+
uint32_t bs = block_size;
48+
49+
// block_tables may be undefined in edge cases (DP empty shard).
50+
const bool has_real_seqs =
51+
n > 0 && host.block_tables.defined() && host.block_tables.dim() >= 2;
52+
if (has_real_seqs) {
53+
auto block_acc = host.block_tables.accessor<int32_t, 2>();
54+
for (int s = 0; s < n; ++s) {
55+
int32_t q_len = host.q_seq_lens[s];
56+
int32_t kv_len = host.kv_seq_lens[s];
57+
m.lens.push_back(static_cast<uint32_t>(q_len));
58+
m.cachedLens.push_back(
59+
static_cast<uint32_t>(std::max(0, kv_len - q_len))); // clamp >= 0
60+
int32_t nblocks =
61+
(kv_len + static_cast<int32_t>(bs) - 1) / static_cast<int32_t>(bs);
62+
std::vector<uint32_t> row(nblocks);
63+
for (int32_t b = 0; b < nblocks; ++b) {
64+
row[b] = static_cast<uint32_t>(block_acc[s][b]);
65+
}
66+
m.blockTables.push_back(std::move(row));
67+
}
68+
}
69+
70+
// DP padding: append dummy seq so sum(lens) aligns across DP groups.
71+
if (pad_count > 0) {
72+
m.lens.push_back(static_cast<uint32_t>(pad_count));
73+
m.cachedLens.push_back(0);
74+
int32_t nblocks =
75+
(static_cast<int32_t>(pad_count) + static_cast<int32_t>(bs) - 1) /
76+
static_cast<int32_t>(bs);
77+
std::vector<uint32_t> row(nblocks, 0);
78+
m.blockTables.push_back(std::move(row));
79+
}
80+
InitXTensor(m.vllmPosition, positions);
81+
}
82+
};
83+
84+
} // namespace xllm::xlite

0 commit comments

Comments
 (0)