94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
508 lines
19 KiB
Plaintext
508 lines
19 KiB
Plaintext
#include <sgl_kernel/tensor.h>
|
|
#include <sgl_kernel/utils.h>
|
|
|
|
#include <sgl_kernel/utils.cuh>
|
|
|
|
#include <dlpack/dlpack.h>
|
|
|
|
#include <algorithm>
|
|
#include <concepts>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <type_traits>
|
|
|
|
namespace device::ngram_embedding {
|
|
|
|
constexpr int kDecodeBlockSize = 256;
|
|
constexpr int kMaxComputeNGramIdsDecodeBlocks = 65535;
|
|
constexpr int kMaxUpdateTokenTableDecodeBlocks = 1024;
|
|
|
|
__global__ void ComputeNGramIdsKernel(
|
|
int batch_size,
|
|
int ne_n,
|
|
int ne_k,
|
|
int* ne_weights, // [ne_n-1,ne_k,ne_n]
|
|
int* ne_mods, // [ne_n-1,ne_k]
|
|
int* exclusive_ne_embeder_size_sums, // [(ne_n-1)*ne_k]
|
|
int* tokens, // [token_num]
|
|
int* exclusive_req_len_sums, // [batch_size+1]
|
|
int* ne_token_table, // [max_running_reqs, max_context_len]
|
|
int max_context_len, // max_context_len
|
|
const int64_t* __restrict__ row_indices, // [batch_size]
|
|
int* column_starts, // [batch_size]
|
|
int* n_gram_ids, // [ne_n-1,ne_k,token_num]
|
|
int eos_token_id // tokens before an eos are excluded from the n-gram context
|
|
) {
|
|
// Determine which n, k, and request this block handles.
|
|
/**
|
|
Example: [req0, req1, req2] with n=3, k=2
|
|
n k req_id blockIdx.x config_id (combination of n and k)
|
|
2 1 0 0 0
|
|
2 1 1 1 0
|
|
2 1 2 2 0
|
|
2 2 0 3 1
|
|
2 2 1 4 1
|
|
2 2 2 5 1
|
|
3 1 0 0 2
|
|
3 1 1 1 2
|
|
3 1 2 2 2
|
|
3 2 0 3 3
|
|
3 2 1 4 3
|
|
3 2 2 5 3
|
|
*/
|
|
const int req_id = blockIdx.x % batch_size;
|
|
const int config_id = (blockIdx.x - req_id) / batch_size;
|
|
// n and k here are offset from their physical meanings: n = real_n - 2, k = real_k - 1.
|
|
// This offset exists because n and k are used as indices into ne_weights and ne_mods.
|
|
const int k = config_id % ne_k;
|
|
const int n = (config_id - config_id % ne_k) / ne_k;
|
|
// ne_weights has shape [ne_n-1, ne_k, ne_n]; last dim is token distance, so compute base index first
|
|
const int ne_weight_base_idx = n * ne_k * ne_n + k * ne_n;
|
|
// ne_mods has shape [ne_n-1, ne_k]
|
|
const int ne_mod = ne_mods[n * ne_k + k];
|
|
// stride loop
|
|
for (int i = exclusive_req_len_sums[req_id] + threadIdx.x; i < exclusive_req_len_sums[req_id + 1]; i += blockDim.x) {
|
|
uint64_t n_gram_id = 0;
|
|
// Token offset within the current request
|
|
const int64_t current_token_offset = i - exclusive_req_len_sums[req_id];
|
|
// Start index of this request in the token table; tokens before this belong to other requests
|
|
const int64_t req_token_table_index = row_indices[req_id] * static_cast<int64_t>(max_context_len);
|
|
// Position of the current token in the token table
|
|
const int64_t current_token_table_index = req_token_table_index + column_starts[req_id] + current_token_offset;
|
|
for (int j = 0; j < n + 2; j++) {
|
|
if (current_token_table_index - j < req_token_table_index) {
|
|
// Out of this request's range, stop computing n_gram_id
|
|
break;
|
|
}
|
|
const int table_token = ne_token_table[current_token_table_index - j];
|
|
if (table_token < 0) {
|
|
// Token was marked as ignored during write
|
|
break;
|
|
}
|
|
if (table_token == eos_token_id && j > 0) {
|
|
// Don't let the n-gram context cross an eos boundary. j==0 (the
|
|
// current token) is allowed; only break when looking back.
|
|
break;
|
|
}
|
|
const uint64_t term = (uint64_t)table_token * (uint64_t)ne_weights[ne_weight_base_idx + j];
|
|
n_gram_id += term % ne_mod;
|
|
}
|
|
n_gram_id %= ne_mod;
|
|
n_gram_id += exclusive_ne_embeder_size_sums[n * ne_k + k];
|
|
// [token_num, ne_n-1, ne_k]
|
|
n_gram_ids[i * (ne_n - 1) * ne_k + n * ne_k + k] = (int)(n_gram_id);
|
|
}
|
|
}
|
|
|
|
__global__ void ComputeNGramIdsDecodeKernel(
|
|
int batch_size,
|
|
int ne_n,
|
|
int ne_k,
|
|
const int* __restrict__ ne_weights, // [ne_n-1,ne_k,ne_n]
|
|
const int* __restrict__ ne_mods, // [ne_n-1,ne_k]
|
|
const int* __restrict__ exclusive_ne_embeder_size_sums, // [(ne_n-1)*ne_k]
|
|
const int* __restrict__ ne_token_table, // [max_running_reqs, max_context_len]
|
|
int max_context_len, // max_context_len
|
|
const int64_t* __restrict__ row_indices, // [batch_size]
|
|
const int* __restrict__ column_starts, // [batch_size]
|
|
int* __restrict__ n_gram_ids, // [batch_size, (ne_n-1)*ne_k]
|
|
int eos_token_id // tokens before an eos are excluded from the n-gram context
|
|
) {
|
|
const int num_configs = (ne_n - 1) * ne_k;
|
|
const int total_outputs = batch_size * num_configs;
|
|
|
|
for (int output_idx = blockIdx.x * blockDim.x + threadIdx.x; output_idx < total_outputs;
|
|
output_idx += blockDim.x * gridDim.x) {
|
|
const int req_id = output_idx / num_configs;
|
|
const int config_idx = output_idx - req_id * num_configs;
|
|
const int k_idx = config_idx % ne_k;
|
|
const int n_idx = config_idx / ne_k;
|
|
const int weight_offset = n_idx * ne_k * ne_n + k_idx * ne_n;
|
|
const int ne_mod = ne_mods[n_idx * ne_k + k_idx];
|
|
|
|
uint64_t n_gram_id = 0;
|
|
const int64_t req_token_table_offset = row_indices[req_id] * static_cast<int64_t>(max_context_len);
|
|
const int64_t current_token_table_offset = req_token_table_offset + column_starts[req_id];
|
|
for (int j = 0; j < n_idx + 2; j++) {
|
|
if (current_token_table_offset - j < req_token_table_offset) {
|
|
break;
|
|
}
|
|
const int token = ne_token_table[current_token_table_offset - j];
|
|
if (token < 0) {
|
|
break;
|
|
}
|
|
if (token == eos_token_id && j > 0) {
|
|
// Don't let the n-gram context cross an eos boundary. j==0 (the
|
|
// current token) is allowed; only break when looking back.
|
|
break;
|
|
}
|
|
const uint64_t term = static_cast<uint64_t>(token) * static_cast<uint64_t>(ne_weights[weight_offset + j]);
|
|
n_gram_id += term % ne_mod;
|
|
}
|
|
n_gram_id %= ne_mod;
|
|
n_gram_id += exclusive_ne_embeder_size_sums[n_idx * ne_k + k_idx];
|
|
n_gram_ids[output_idx] = static_cast<int>(n_gram_id);
|
|
}
|
|
}
|
|
|
|
__global__ void UpdateTokenTableKernel(
|
|
int batch_size,
|
|
int* tokens, // [token_num]
|
|
int* ne_token_table, // [max_running_reqs, max_context_len]
|
|
int max_context_len, // max_context_len
|
|
const int64_t* __restrict__ row_indices, // [batch_size]
|
|
int* column_starts, // [batch_size]
|
|
int* req_lens, // [batch_size]
|
|
int ignore_token_num, // number of tokens to ignore
|
|
int* ignore_tokens // [ignore_token_num]
|
|
) {
|
|
// Each block processes one request.
|
|
const int req_id = blockIdx.x % batch_size;
|
|
int start = 0;
|
|
int end = 0;
|
|
for (int i = 0; i < req_id; i++) {
|
|
start += req_lens[i];
|
|
}
|
|
end = start + req_lens[req_id];
|
|
// stride loop
|
|
for (int i = start + threadIdx.x; i < end; i += blockDim.x) {
|
|
// Token offset within the current request
|
|
const int64_t current_token_offset = i - start;
|
|
// Start index of this request in the token table
|
|
const int64_t req_token_table_index = row_indices[req_id] * static_cast<int64_t>(max_context_len);
|
|
// Position of the current token in the token table
|
|
const int64_t current_token_table_index = req_token_table_index + column_starts[req_id] + current_token_offset;
|
|
ne_token_table[current_token_table_index] = tokens[i];
|
|
for (int j = 0; j < ignore_token_num; j++) {
|
|
if (ignore_tokens[j] == tokens[i]) {
|
|
ne_token_table[current_token_table_index] = -tokens[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
__global__ void UpdateTokenTableDecodeKernel(
|
|
int batch_size,
|
|
const int* __restrict__ tokens, // [batch_size]
|
|
int* __restrict__ ne_token_table, // [max_running_reqs, max_context_len]
|
|
int max_context_len, // max_context_len
|
|
const int64_t* __restrict__ row_indices, // [batch_size]
|
|
const int* __restrict__ column_starts // [batch_size]
|
|
) {
|
|
for (int req_id = blockIdx.x * blockDim.x + threadIdx.x; req_id < batch_size; req_id += blockDim.x * gridDim.x) {
|
|
const int64_t token_table_offset =
|
|
row_indices[req_id] * static_cast<int64_t>(max_context_len) + column_starts[req_id];
|
|
ne_token_table[token_table_offset] = tokens[req_id];
|
|
}
|
|
}
|
|
|
|
} // namespace device::ngram_embedding
|
|
|
|
namespace {
|
|
|
|
struct NgramEmbeddingKernel {
|
|
static void compute_n_gram_ids(
|
|
const int64_t ne_n,
|
|
const int64_t ne_k,
|
|
const tvm::ffi::TensorView ne_weights,
|
|
const tvm::ffi::TensorView ne_mods,
|
|
const tvm::ffi::TensorView exclusive_ne_embeder_size_sums,
|
|
const tvm::ffi::TensorView tokens,
|
|
const tvm::ffi::TensorView exclusive_req_len_sums,
|
|
const tvm::ffi::TensorView ne_token_table,
|
|
const tvm::ffi::TensorView row_indices,
|
|
const tvm::ffi::TensorView column_starts,
|
|
const tvm::ffi::TensorView n_gram_ids,
|
|
const int64_t eos_token_id) {
|
|
using namespace host;
|
|
|
|
auto device_ = SymbolicDevice{};
|
|
|
|
// Verify tensor shapes and types using -1 (kAnySize) for dynamic dimensions
|
|
TensorMatcher({-1, -1, -1}) // [ne_n-1, ne_k, ne_n]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>(device_)
|
|
.verify(ne_weights);
|
|
|
|
TensorMatcher({-1, -1}) // [ne_n-1, ne_k]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(ne_mods);
|
|
|
|
TensorMatcher({-1}) // [(ne_n-1)*ne_k + 1]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(exclusive_ne_embeder_size_sums);
|
|
|
|
TensorMatcher({-1}) // [token_num]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(tokens);
|
|
|
|
TensorMatcher({-1}) // [batch_size+1]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(exclusive_req_len_sums);
|
|
|
|
TensorMatcher({-1, -1}) // [max_running_reqs, max_context_len]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(ne_token_table);
|
|
|
|
TensorMatcher({-1}) // [batch_size]
|
|
.with_dtype<int64_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(row_indices);
|
|
|
|
TensorMatcher({-1}) // [batch_size]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(column_starts);
|
|
|
|
TensorMatcher({-1, -1}) // [token_num, (ne_n-1)*ne_k]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(n_gram_ids);
|
|
|
|
const int batch_size = static_cast<int>(exclusive_req_len_sums.size(0) - 1);
|
|
const int max_context_len = static_cast<int>(ne_token_table.size(1));
|
|
const auto stream = LaunchKernel::resolve_device(device_.unwrap());
|
|
|
|
constexpr int BLOCK_THREADS = 256;
|
|
const int num_configs = (static_cast<int>(ne_n) - 1) * static_cast<int>(ne_k);
|
|
const int grid_size = num_configs * batch_size;
|
|
|
|
LaunchKernel(grid_size, BLOCK_THREADS, stream)(
|
|
device::ngram_embedding::ComputeNGramIdsKernel,
|
|
batch_size,
|
|
static_cast<int>(ne_n),
|
|
static_cast<int>(ne_k),
|
|
static_cast<int*>(ne_weights.data_ptr()),
|
|
static_cast<int*>(ne_mods.data_ptr()),
|
|
static_cast<int*>(exclusive_ne_embeder_size_sums.data_ptr()),
|
|
static_cast<int*>(tokens.data_ptr()),
|
|
static_cast<int*>(exclusive_req_len_sums.data_ptr()),
|
|
static_cast<int*>(ne_token_table.data_ptr()),
|
|
max_context_len,
|
|
static_cast<const int64_t*>(row_indices.data_ptr()),
|
|
static_cast<int*>(column_starts.data_ptr()),
|
|
static_cast<int*>(n_gram_ids.data_ptr()),
|
|
static_cast<int>(eos_token_id));
|
|
}
|
|
|
|
static void compute_n_gram_ids_decode(
|
|
const int64_t ne_n,
|
|
const int64_t ne_k,
|
|
const tvm::ffi::TensorView ne_weights,
|
|
const tvm::ffi::TensorView ne_mods,
|
|
const tvm::ffi::TensorView exclusive_ne_embeder_size_sums,
|
|
const tvm::ffi::TensorView ne_token_table,
|
|
const tvm::ffi::TensorView row_indices,
|
|
const tvm::ffi::TensorView column_starts,
|
|
const tvm::ffi::TensorView n_gram_ids,
|
|
const int64_t eos_token_id) {
|
|
using namespace host;
|
|
|
|
auto device_ = SymbolicDevice{};
|
|
auto batch_size = SymbolicSize{"batch_size"};
|
|
|
|
TensorMatcher({-1, -1, -1}) // [ne_n-1, ne_k, ne_n]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>(device_)
|
|
.verify(ne_weights);
|
|
|
|
TensorMatcher({-1, -1}) // [ne_n-1, ne_k]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(ne_mods);
|
|
|
|
TensorMatcher({-1}) // [(ne_n-1)*ne_k + 1]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(exclusive_ne_embeder_size_sums);
|
|
|
|
TensorMatcher({-1, -1}) // [max_running_reqs, max_context_len]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(ne_token_table);
|
|
|
|
TensorMatcher({batch_size}) // [batch_size]
|
|
.with_dtype<int64_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(row_indices);
|
|
|
|
TensorMatcher({batch_size}) // [batch_size]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(column_starts);
|
|
|
|
TensorMatcher({batch_size, -1}) // [batch_size, (ne_n-1)*ne_k]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(n_gram_ids);
|
|
|
|
const int bs = static_cast<int>(batch_size.unwrap());
|
|
if (bs <= 0) {
|
|
return;
|
|
}
|
|
|
|
const int max_context_len = static_cast<int>(ne_token_table.size(1));
|
|
const int num_configs = (static_cast<int>(ne_n) - 1) * static_cast<int>(ne_k);
|
|
const int total_outputs = bs * num_configs;
|
|
const auto stream = LaunchKernel::resolve_device(device_.unwrap());
|
|
|
|
constexpr int kBlockSize = device::ngram_embedding::kDecodeBlockSize;
|
|
const int grid_size = std::min(
|
|
device::ngram_embedding::kMaxComputeNGramIdsDecodeBlocks,
|
|
static_cast<int>(div_ceil(total_outputs, kBlockSize)));
|
|
|
|
LaunchKernel(grid_size, kBlockSize, stream)(
|
|
device::ngram_embedding::ComputeNGramIdsDecodeKernel,
|
|
bs,
|
|
static_cast<int>(ne_n),
|
|
static_cast<int>(ne_k),
|
|
static_cast<const int*>(ne_weights.data_ptr()),
|
|
static_cast<const int*>(ne_mods.data_ptr()),
|
|
static_cast<const int*>(exclusive_ne_embeder_size_sums.data_ptr()),
|
|
static_cast<const int*>(ne_token_table.data_ptr()),
|
|
max_context_len,
|
|
static_cast<const int64_t*>(row_indices.data_ptr()),
|
|
static_cast<const int*>(column_starts.data_ptr()),
|
|
static_cast<int*>(n_gram_ids.data_ptr()),
|
|
static_cast<int>(eos_token_id));
|
|
}
|
|
|
|
static void update_token_table(
|
|
const tvm::ffi::TensorView tokens,
|
|
const tvm::ffi::TensorView ne_token_table,
|
|
const tvm::ffi::TensorView row_indices,
|
|
const tvm::ffi::TensorView column_starts,
|
|
const tvm::ffi::TensorView req_lens,
|
|
const tvm::ffi::TensorView ignore_tokens) {
|
|
using namespace host;
|
|
|
|
auto device_ = SymbolicDevice{};
|
|
|
|
// Verify tensor shapes and types using -1 (kAnySize) for dynamic dimensions
|
|
TensorMatcher({-1}) // [token_num]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>(device_)
|
|
.verify(tokens);
|
|
|
|
TensorMatcher({-1, -1}) // [max_running_reqs, max_context_len]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(ne_token_table);
|
|
|
|
TensorMatcher({-1}) // [batch_size]
|
|
.with_dtype<int64_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(row_indices);
|
|
|
|
TensorMatcher({-1}) // [batch_size]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(column_starts);
|
|
|
|
TensorMatcher({-1}) // [batch_size]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(req_lens);
|
|
|
|
// ignore_tokens can be empty or have values
|
|
void* ignore_tokens_ptr = ignore_tokens.data_ptr();
|
|
const bool has_ignore_tokens = ignore_tokens_ptr != nullptr && ignore_tokens.numel() > 0;
|
|
if (has_ignore_tokens) {
|
|
TensorMatcher({-1}) // [ignore_token_num]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(ignore_tokens);
|
|
}
|
|
|
|
const int batch_size = static_cast<int>(req_lens.size(0));
|
|
if (batch_size <= 0) {
|
|
return;
|
|
}
|
|
|
|
const int max_context_len = static_cast<int>(ne_token_table.size(1));
|
|
const auto stream = LaunchKernel::resolve_device(device_.unwrap());
|
|
|
|
constexpr int BLOCK_THREADS = 256;
|
|
const int grid_size = batch_size;
|
|
|
|
int ignore_token_num = 0;
|
|
int* ignore_tokens_typed_ptr = nullptr;
|
|
if (has_ignore_tokens) {
|
|
ignore_token_num = static_cast<int>(ignore_tokens.numel());
|
|
ignore_tokens_typed_ptr = static_cast<int*>(ignore_tokens_ptr);
|
|
}
|
|
|
|
LaunchKernel(grid_size, BLOCK_THREADS, stream)(
|
|
device::ngram_embedding::UpdateTokenTableKernel,
|
|
batch_size,
|
|
static_cast<int*>(tokens.data_ptr()),
|
|
static_cast<int*>(ne_token_table.data_ptr()),
|
|
max_context_len,
|
|
static_cast<const int64_t*>(row_indices.data_ptr()),
|
|
static_cast<int*>(column_starts.data_ptr()),
|
|
static_cast<int*>(req_lens.data_ptr()),
|
|
ignore_token_num,
|
|
ignore_tokens_typed_ptr);
|
|
}
|
|
|
|
static void update_token_table_decode(
|
|
const tvm::ffi::TensorView tokens,
|
|
const tvm::ffi::TensorView ne_token_table,
|
|
const tvm::ffi::TensorView row_indices,
|
|
const tvm::ffi::TensorView column_starts) {
|
|
using namespace host;
|
|
|
|
auto batch_size = SymbolicSize{"batch_size"};
|
|
auto device_ = SymbolicDevice{};
|
|
|
|
TensorMatcher({batch_size}) // [batch_size]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>(device_)
|
|
.verify(tokens);
|
|
|
|
TensorMatcher({-1, -1}) // [max_running_reqs, max_context_len]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(ne_token_table);
|
|
|
|
TensorMatcher({batch_size}) // [batch_size]
|
|
.with_dtype<int64_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(row_indices);
|
|
|
|
TensorMatcher({batch_size}) // [batch_size]
|
|
.with_dtype<int32_t>()
|
|
.with_device<kDLGPU>()
|
|
.verify(column_starts);
|
|
|
|
const int bs = static_cast<int>(batch_size.unwrap());
|
|
if (bs <= 0) {
|
|
return;
|
|
}
|
|
|
|
const int max_context_len = static_cast<int>(ne_token_table.size(1));
|
|
const auto stream = LaunchKernel::resolve_device(device_.unwrap());
|
|
|
|
constexpr int kBlockSize = device::ngram_embedding::kDecodeBlockSize;
|
|
const int grid_size = std::min(
|
|
device::ngram_embedding::kMaxUpdateTokenTableDecodeBlocks, static_cast<int>(host::div_ceil(bs, kBlockSize)));
|
|
|
|
LaunchKernel(grid_size, kBlockSize, stream)(
|
|
device::ngram_embedding::UpdateTokenTableDecodeKernel,
|
|
bs,
|
|
static_cast<const int*>(tokens.data_ptr()),
|
|
static_cast<int*>(ne_token_table.data_ptr()),
|
|
max_context_len,
|
|
static_cast<const int64_t*>(row_indices.data_ptr()),
|
|
static_cast<const int*>(column_starts.data_ptr()));
|
|
}
|
|
};
|
|
|
|
} // namespace
|