[Spec][Ngram] 4/N: Remove max_match_window_size and min_match_window_size, matching all suffixes of the Trie (#21225)
This commit is contained in:
@@ -506,8 +506,6 @@ class ServerArgs:
|
||||
speculative_draft_model_quantization: Optional[str] = None
|
||||
|
||||
# Speculative decoding (ngram)
|
||||
speculative_ngram_min_match_window_size: int = 1
|
||||
speculative_ngram_max_match_window_size: int = 12
|
||||
speculative_ngram_min_bfs_breadth: int = 1
|
||||
speculative_ngram_max_bfs_breadth: int = 10
|
||||
speculative_ngram_match_type: Literal["BFS", "PROB"] = "BFS"
|
||||
@@ -3108,8 +3106,10 @@ class ServerArgs:
|
||||
self.enable_mixed_chunk = False
|
||||
self.speculative_eagle_topk = self.speculative_ngram_max_bfs_breadth
|
||||
if self.speculative_num_draft_tokens is None:
|
||||
self.speculative_num_draft_tokens = (
|
||||
self.speculative_ngram_max_match_window_size
|
||||
self.speculative_num_draft_tokens = 12
|
||||
logger.warning(
|
||||
"speculative_num_draft_tokens is set to 12 by default for ngram speculative decoding. "
|
||||
"You can override this by explicitly setting --speculative-num-draft-tokens."
|
||||
)
|
||||
logger.warning(
|
||||
"The overlap scheduler and mixed chunked prefill are disabled because of "
|
||||
@@ -4851,18 +4851,6 @@ class ServerArgs:
|
||||
)
|
||||
|
||||
# Speculative decoding (ngram)
|
||||
parser.add_argument(
|
||||
"--speculative-ngram-min-match-window-size",
|
||||
type=int,
|
||||
default=ServerArgs.speculative_ngram_min_match_window_size,
|
||||
help="The minimum window size for pattern matching in ngram speculative decoding.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--speculative-ngram-max-match-window-size",
|
||||
type=int,
|
||||
default=ServerArgs.speculative_ngram_max_match_window_size,
|
||||
help="The maximum window size for pattern matching in ngram speculative decoding.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--speculative-ngram-min-bfs-breadth",
|
||||
type=int,
|
||||
|
||||
@@ -13,23 +13,6 @@ Ngram::Ngram(size_t capacity, const Param& param) : param_(param) {
|
||||
throw std::runtime_error(
|
||||
"param_.max_trie_depth must be greater than 1, current value: " + std::to_string(param_.max_trie_depth));
|
||||
}
|
||||
if (!(param_.min_match_window_size > 0)) {
|
||||
throw std::runtime_error(
|
||||
"min_match_window_size must be greater than 0, current value: " + std::to_string(param_.min_match_window_size));
|
||||
}
|
||||
if (!(param_.min_match_window_size <= param_.max_match_window_size)) {
|
||||
throw std::runtime_error(
|
||||
"min_match_window_size must be less than or equal to "
|
||||
"max_match_window_size, current min_match_window_size: " +
|
||||
std::to_string(param_.min_match_window_size) +
|
||||
", max_match_window_size: " + std::to_string(param_.max_match_window_size));
|
||||
}
|
||||
if (!(param_.max_match_window_size < param_.max_trie_depth)) {
|
||||
throw std::runtime_error(
|
||||
"max_match_window_size must be less than max_trie_depth, current "
|
||||
"max_match_window_size: " +
|
||||
std::to_string(param_.max_match_window_size) + ", max_trie_depth: " + std::to_string(param_.max_trie_depth));
|
||||
}
|
||||
if (!(param_.min_bfs_breadth > 0)) {
|
||||
throw std::runtime_error(
|
||||
"min_bfs_breadth must be greater than 0, current value: " + std::to_string(param_.min_bfs_breadth));
|
||||
@@ -53,20 +36,6 @@ Ngram::Ngram(size_t capacity, const Param& param) : param_(param) {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto config : param_.batch_min_match_window_size) {
|
||||
if (config != std::numeric_limits<decltype(config)>::max()) {
|
||||
if (!(config >= param_.min_match_window_size)) {
|
||||
throw std::runtime_error(
|
||||
"batch_min_match_window_size config value " + std::to_string(config) +
|
||||
" must be greater than or equal to min_match_window_size: " + std::to_string(param_.min_match_window_size));
|
||||
}
|
||||
if (!(config <= param_.max_match_window_size)) {
|
||||
throw std::runtime_error(
|
||||
"batch_min_match_window_size config value " + std::to_string(config) +
|
||||
" must be less than or equal to max_match_window_size: " + std::to_string(param_.max_match_window_size));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trie_ = std::make_unique<Trie>(capacity, param_);
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@ class NgramCorpus:
|
||||
def __init__(
|
||||
self,
|
||||
max_trie_depth=18,
|
||||
min_match_window_size=1,
|
||||
max_match_window_size=10,
|
||||
min_bfs_breadth=1,
|
||||
max_bfs_breadth=8,
|
||||
draft_token_num=8,
|
||||
@@ -36,8 +34,6 @@ class NgramCorpus:
|
||||
):
|
||||
param = ngram_corpus_cpp.Param()
|
||||
param.max_trie_depth = max_trie_depth
|
||||
param.min_match_window_size = min_match_window_size
|
||||
param.max_match_window_size = max_match_window_size
|
||||
param.min_bfs_breadth = min_bfs_breadth
|
||||
param.max_bfs_breadth = max_bfs_breadth
|
||||
param.draft_token_num = draft_token_num
|
||||
|
||||
@@ -21,17 +21,12 @@ PYBIND11_MODULE(ngram_corpus_cpp, m) {
|
||||
.def_readwrite("enable_router_mode", &Param::enable_router_mode)
|
||||
.def_readwrite("min_bfs_breadth", &Param::min_bfs_breadth)
|
||||
.def_readwrite("max_bfs_breadth", &Param::max_bfs_breadth)
|
||||
.def_readwrite("min_match_window_size", &Param::min_match_window_size)
|
||||
.def_readwrite("max_match_window_size", &Param::max_match_window_size)
|
||||
.def_readwrite("max_trie_depth", &Param::max_trie_depth)
|
||||
.def_readwrite("draft_token_num", &Param::draft_token_num)
|
||||
.def_readwrite("match_type", &Param::match_type)
|
||||
.def_readwrite("batch_min_match_window_size", &Param::batch_min_match_window_size)
|
||||
.def_readwrite("batch_draft_token_num", &Param::batch_draft_token_num)
|
||||
.def("get_draft_token_num", &Param::get_draft_token_num, "")
|
||||
.def("get_min_match_window_size", &Param::get_min_match_window_size, "")
|
||||
.def("parse", &Param::parse, "")
|
||||
.def("resetBatchMinMatchWindowSize", &Param::resetBatchMinMatchWindowSize, "")
|
||||
.def("resetBatchReturnTokenNum", &Param::resetBatchReturnTokenNum, "")
|
||||
.def("detail", &Param::detail, "");
|
||||
|
||||
|
||||
@@ -17,13 +17,10 @@ struct Param {
|
||||
bool enable_router_mode;
|
||||
size_t min_bfs_breadth;
|
||||
size_t max_bfs_breadth;
|
||||
size_t min_match_window_size;
|
||||
size_t max_match_window_size;
|
||||
size_t max_trie_depth;
|
||||
size_t draft_token_num;
|
||||
std::string match_type;
|
||||
|
||||
std::vector<size_t> batch_min_match_window_size;
|
||||
std::vector<size_t> batch_draft_token_num;
|
||||
|
||||
size_t get_draft_token_num(size_t batch_size) const {
|
||||
@@ -36,16 +33,6 @@ struct Param {
|
||||
return draft_token_num - 1;
|
||||
}
|
||||
|
||||
size_t get_min_match_window_size(size_t batch_size) const {
|
||||
if (batch_size < batch_min_match_window_size.size()) {
|
||||
if (batch_min_match_window_size[batch_size] !=
|
||||
std::numeric_limits<decltype(batch_min_match_window_size)::value_type>::max()) {
|
||||
return batch_min_match_window_size[batch_size];
|
||||
}
|
||||
}
|
||||
return min_match_window_size;
|
||||
}
|
||||
|
||||
std::vector<size_t> parse(const std::string& value) {
|
||||
// 0-1|10,2-3|20,
|
||||
std::vector<size_t> result;
|
||||
@@ -96,10 +83,6 @@ struct Param {
|
||||
return result;
|
||||
}
|
||||
|
||||
void resetBatchMinMatchWindowSize(const std::string& value) {
|
||||
batch_min_match_window_size = parse(value);
|
||||
}
|
||||
|
||||
void resetBatchReturnTokenNum(const std::string& value) {
|
||||
batch_draft_token_num = parse(value);
|
||||
}
|
||||
@@ -108,13 +91,8 @@ struct Param {
|
||||
std::stringstream ss;
|
||||
ss << "enable = " << enable << ", enable_router_mode = " << enable_router_mode
|
||||
<< ", min_bfs_breadth = " << min_bfs_breadth << ", max_bfs_breadth = " << max_bfs_breadth
|
||||
<< ", min_match_window_size = " << min_match_window_size << ", max_match_window_size = " << max_match_window_size
|
||||
<< ", max_trie_depth = " << max_trie_depth << ", draft_token_num = " << draft_token_num
|
||||
<< ", match_type = " << match_type;
|
||||
ss << ", batch_min_match_window_size(" << batch_min_match_window_size.size() << ") = ";
|
||||
for (int i = 0; i < batch_min_match_window_size.size(); ++i) {
|
||||
ss << i << "|" << batch_min_match_window_size[i] << ",";
|
||||
}
|
||||
ss << ", batch_draft_token_num(" << batch_draft_token_num.size() << ") = ";
|
||||
for (int i = 0; i < batch_draft_token_num.size(); ++i) {
|
||||
ss << i << "|" << batch_draft_token_num[i] << ",";
|
||||
|
||||
@@ -19,7 +19,7 @@ Trie::Trie(size_t capacity, const Param& param) : param_(param) {
|
||||
}
|
||||
|
||||
void Trie::insert(const int32_t* tokens, size_t len) {
|
||||
for (size_t i = 0; i + param_.min_match_window_size < len; ++i) {
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
auto start = tokens + i;
|
||||
auto end = start + std::min(len - i, param_.max_trie_depth);
|
||||
|
||||
@@ -100,14 +100,13 @@ void Trie::reset() {
|
||||
root_ = getNode();
|
||||
}
|
||||
|
||||
std::vector<std::pair<TrieNode*, int32_t>>
|
||||
Trie::match(const int32_t* context, size_t len, size_t min_window, size_t max_window) const {
|
||||
std::vector<std::pair<TrieNode*, int32_t>> Trie::match(const int32_t* context, size_t len) const {
|
||||
std::vector<std::pair<TrieNode*, int32_t>> result;
|
||||
result.reserve(max_window - min_window);
|
||||
for (int32_t match_window_size = std::min(len, max_window); match_window_size >= static_cast<int32_t>(min_window);
|
||||
--match_window_size) {
|
||||
auto start = context + len - match_window_size;
|
||||
auto end = start + match_window_size;
|
||||
const auto max_match_depth = std::min(len, param_.max_trie_depth);
|
||||
result.reserve(max_match_depth);
|
||||
for (size_t match_depth = max_match_depth; match_depth > 0; --match_depth) {
|
||||
auto start = context + len - match_depth;
|
||||
auto end = start + match_depth;
|
||||
auto cursor = root_;
|
||||
while (start != end) {
|
||||
auto iter = cursor->child.find(*start);
|
||||
@@ -118,8 +117,8 @@ Trie::match(const int32_t* context, size_t len, size_t min_window, size_t max_wi
|
||||
++start;
|
||||
cursor = iter->second;
|
||||
}
|
||||
if (cursor) {
|
||||
result.emplace_back(std::make_pair(cursor, match_window_size));
|
||||
if (cursor != nullptr && !cursor->child.empty()) {
|
||||
result.emplace_back(cursor, static_cast<int32_t>(match_depth));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -127,10 +126,10 @@ Trie::match(const int32_t* context, size_t len, size_t min_window, size_t max_wi
|
||||
|
||||
Result Trie::buildRecency(
|
||||
const int32_t* context, size_t len, int32_t last_token, size_t draft_token_num, const Param& param) const {
|
||||
auto anchors = match(context, len, param.min_match_window_size, param.max_match_window_size);
|
||||
auto anchors = match(context, len);
|
||||
|
||||
double bfs_breadth_scale = double(param.max_bfs_breadth - param.min_bfs_breadth) /
|
||||
(param.max_match_window_size - param.min_match_window_size + 1);
|
||||
const auto max_match_depth = std::max<int32_t>(1, static_cast<int32_t>(param.max_trie_depth - 1));
|
||||
double bfs_breadth_scale = double(param.max_bfs_breadth - param.min_bfs_breadth) / max_match_depth;
|
||||
|
||||
std::vector<Node> tree(draft_token_num + 1);
|
||||
int root = 0;
|
||||
@@ -138,7 +137,7 @@ Result Trie::buildRecency(
|
||||
|
||||
for (auto [node, depth] : anchors) {
|
||||
std::queue<std::tuple<int32_t, double, const TrieNode*>> queue;
|
||||
queue.push({root, (param.max_match_window_size - depth) * bfs_breadth_scale + param.min_bfs_breadth, node});
|
||||
queue.push({root, (max_match_depth - depth) * bfs_breadth_scale + param.min_bfs_breadth, node});
|
||||
while (queue.size() && cursor <= static_cast<int>(draft_token_num)) {
|
||||
auto front = queue.front();
|
||||
queue.pop();
|
||||
@@ -168,7 +167,7 @@ Result Trie::buildRecency(
|
||||
|
||||
Result Trie::buildFrequency(
|
||||
const int32_t* context, size_t len, int32_t last_token, size_t draft_token_num, const Param& param) const {
|
||||
auto anchors = match(context, len, param.min_match_window_size, param.max_match_window_size);
|
||||
auto anchors = match(context, len);
|
||||
|
||||
struct CompareByLastDouble {
|
||||
bool operator()(
|
||||
|
||||
@@ -49,8 +49,7 @@ class Trie {
|
||||
void reset();
|
||||
|
||||
private:
|
||||
std::vector<std::pair<TrieNode*, int32_t>>
|
||||
match(const int32_t* context, size_t len, size_t min_window, size_t max_window) const;
|
||||
std::vector<std::pair<TrieNode*, int32_t>> match(const int32_t* context, size_t len) const;
|
||||
|
||||
TrieNode* getNode() {
|
||||
auto node = node_pool_[--free_node_count_];
|
||||
|
||||
@@ -41,9 +41,6 @@ class NGRAMWorker:
|
||||
self.page_size = server_args.page_size
|
||||
self.draft_token_num: int = server_args.speculative_num_draft_tokens
|
||||
self.max_trie_depth: int = server_args.speculative_ngram_max_trie_depth
|
||||
self.max_match_window_size: int = (
|
||||
server_args.speculative_ngram_max_match_window_size
|
||||
)
|
||||
|
||||
self.max_batch_size = target_worker.max_running_requests
|
||||
self.device = f"cuda:{gpu_id}" if gpu_id >= 0 else "cuda"
|
||||
@@ -51,8 +48,6 @@ class NGRAMWorker:
|
||||
self._init_preallocated_tensors()
|
||||
|
||||
self.ngram_corpus = NgramCorpus(
|
||||
min_match_window_size=server_args.speculative_ngram_min_match_window_size,
|
||||
max_match_window_size=server_args.speculative_ngram_max_match_window_size,
|
||||
min_bfs_breadth=server_args.speculative_ngram_min_bfs_breadth,
|
||||
max_bfs_breadth=server_args.speculative_ngram_max_bfs_breadth,
|
||||
match_type=server_args.speculative_ngram_match_type,
|
||||
@@ -131,7 +126,7 @@ class NGRAMWorker:
|
||||
batch_tokens = []
|
||||
for req in batch.reqs:
|
||||
check_token = self._efficient_concat_last_n(
|
||||
req.origin_input_ids, req.output_ids, self.max_match_window_size
|
||||
req.origin_input_ids, req.output_ids, self.max_trie_depth
|
||||
)
|
||||
batch_tokens.append(check_token)
|
||||
req_drafts, mask = self.ngram_corpus.batch_get(batch_tokens)
|
||||
|
||||
@@ -768,8 +768,6 @@ def run_lora_multiple_batch_on_model_cases(
|
||||
else {
|
||||
"speculative_algorithm": "NGRAM",
|
||||
"speculative_num_draft_tokens": 5,
|
||||
"speculative_ngram_min_match_window_size": 2,
|
||||
"speculative_ngram_max_match_window_size": 15,
|
||||
}
|
||||
)
|
||||
srt_runner = SRTRunner(
|
||||
|
||||
@@ -574,8 +574,6 @@ class SRTRunner:
|
||||
speculative_num_steps: Optional[int] = None,
|
||||
speculative_eagle_topk: Optional[int] = None,
|
||||
speculative_num_draft_tokens: Optional[int] = None,
|
||||
speculative_ngram_min_match_window_size: Optional[int] = None,
|
||||
speculative_ngram_max_match_window_size: Optional[int] = None,
|
||||
disable_overlap_schedule: bool = False,
|
||||
disable_custom_all_reduce: bool = False,
|
||||
torchao_config: Optional[str] = None,
|
||||
@@ -606,12 +604,7 @@ class SRTRunner:
|
||||
spec_kwargs["speculative_num_draft_tokens"] = speculative_num_draft_tokens
|
||||
elif speculative_algorithm == "NGRAM":
|
||||
spec_kwargs["speculative_algorithm"] = speculative_algorithm
|
||||
spec_kwargs["speculative_ngram_min_match_window_size"] = (
|
||||
speculative_ngram_min_match_window_size
|
||||
)
|
||||
spec_kwargs["speculative_ngram_max_match_window_size"] = (
|
||||
speculative_ngram_max_match_window_size
|
||||
)
|
||||
spec_kwargs["speculative_num_draft_tokens"] = speculative_num_draft_tokens
|
||||
|
||||
self.engine = Engine(
|
||||
model_path=model_path,
|
||||
|
||||
Reference in New Issue
Block a user