Files
wehub-resource-sync 7ce4c8e27e
pre-commit / pre-run-check (push) Has been cancelled
pre-commit / pre-commit (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:55:37 +08:00

97 lines
4.2 KiB
Plaintext

// N-gram embedding index kernel for LongCat-Flash (n-gram embedding variant).
//
// Adapted from SGLang:
// https://github.com/sgl-project/sglang/blob/main/python/sglang/jit_kernel/csrc/ngram_embedding.cuh
//
// For each position, computes the hashed n-gram embedding ids that index the
// concatenated embedder table. Integer tensors are int32 except ``row_indices``
// (int64); the token table is ``[max_running_reqs, max_context_len]`` int32,
// where a negative entry marks an ignored token (e.g. an EOS boundary).
#include "torch_utils.h"
#include "ops.h"
#include <cstdint>
namespace vllm::ngram_embedding {
constexpr int kBlockThreads = 256;
__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_embedder_size_sums, // [(ne_n-1)*ne_k + 1]
int* exclusive_req_len_sums, // [batch_size + 1]
int* ne_token_table, // [max_running_reqs, max_context_len]
int max_context_len,
const int64_t* __restrict__ row_indices, // [batch_size]
int* column_starts, // [batch_size]
int* n_gram_ids // [token_num, (ne_n-1)*ne_k]
) {
const int req_id = blockIdx.x % batch_size;
const int config_id = (blockIdx.x - req_id) / batch_size;
// n and k are offset from their physical meaning: n = real_n - 2, k = real_k
// - 1 (they index into ne_weights / ne_mods).
const int k = config_id % ne_k;
const int n = (config_id - config_id % ne_k) / ne_k;
const int ne_weight_base_idx = n * ne_k * ne_n + k * ne_n;
const int ne_mod = ne_mods[n * ne_k + k];
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;
const int64_t current_token_offset = i - exclusive_req_len_sums[req_id];
const int64_t req_token_table_index =
row_indices[req_id] * static_cast<int64_t>(max_context_len);
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) {
break; // outside this request's range
}
if (ne_token_table[current_token_table_index - j] < 0) {
break; // ignored token
}
const uint64_t term =
(uint64_t)ne_token_table[current_token_table_index - j] *
(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_embedder_size_sums[n * ne_k + k];
n_gram_ids[i * (ne_n - 1) * ne_k + n * ne_k + k] = (int)(n_gram_id);
}
}
} // namespace vllm::ngram_embedding
void ngram_compute_n_gram_ids(
int64_t ne_n, int64_t ne_k, torch::stable::Tensor& ne_weights,
torch::stable::Tensor& ne_mods,
torch::stable::Tensor& exclusive_ne_embedder_size_sums,
torch::stable::Tensor& exclusive_req_len_sums,
torch::stable::Tensor& ne_token_table, torch::stable::Tensor& row_indices,
torch::stable::Tensor& column_starts, torch::stable::Tensor& 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 int num_configs = (static_cast<int>(ne_n) - 1) * static_cast<int>(ne_k);
const int grid_size = num_configs * batch_size;
if (grid_size <= 0) return;
const torch::stable::accelerator::DeviceGuard device_guard(
ne_weights.get_device_index());
const cudaStream_t stream = get_current_cuda_stream();
vllm::ngram_embedding::ComputeNGramIdsKernel<<<
grid_size, vllm::ngram_embedding::kBlockThreads, 0, stream>>>(
batch_size, static_cast<int>(ne_n), static_cast<int>(ne_k),
ne_weights.mutable_data_ptr<int32_t>(),
ne_mods.mutable_data_ptr<int32_t>(),
exclusive_ne_embedder_size_sums.mutable_data_ptr<int32_t>(),
exclusive_req_len_sums.mutable_data_ptr<int32_t>(),
ne_token_table.mutable_data_ptr<int32_t>(), max_context_len,
row_indices.const_data_ptr<int64_t>(),
column_starts.mutable_data_ptr<int32_t>(),
n_gram_ids.mutable_data_ptr<int32_t>());
}