Skip to content

Commit 4b48a53

Browse files
authored
server : optimize get_token_probabilities (ggml-org#24796)
Use std::partial_sort to order only the requested top-n tokens instead of the full vocabulary logprobs sort: vocab=128000 n_top=0 iters=100 full sort: 8555.6 us/op partial sort: 704.3 us/op Signed-off-by: Adrien Gallouët <angt@huggingface.co>
1 parent e475fa2 commit 4b48a53

3 files changed

Lines changed: 27 additions & 14 deletions

File tree

tools/server/server-common.cpp

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <random>
1313
#include <sstream>
1414
#include <fstream>
15+
#include <limits>
1516

1617
json format_error_response(const std::string & message, const enum error_type type) {
1718
std::string type_str;
@@ -1238,7 +1239,7 @@ json format_response_rerank(
12381239
// other utils
12391240
//
12401241

1241-
std::vector<llama_token_data> get_token_probabilities(llama_context * ctx, int idx) {
1242+
std::vector<llama_token_data> get_token_probabilities(llama_context * ctx, int idx, size_t n_top) {
12421243
std::vector<llama_token_data> cur;
12431244

12441245
const auto * logits = llama_get_logits_ith(ctx, idx);
@@ -1257,21 +1258,34 @@ std::vector<llama_token_data> get_token_probabilities(llama_context * ctx, int i
12571258
}
12581259
}
12591260

1260-
// sort tokens by logits
1261-
std::sort(cur.begin(), cur.end(), [](const llama_token_data & a, const llama_token_data & b) {
1262-
return a.logit > b.logit;
1263-
});
1261+
// sort tokens by logits (partial: only the leading `n_top` need ordering)
1262+
if (n_top > cur.size()) {
1263+
n_top = cur.size();
1264+
}
1265+
if (n_top > 0) {
1266+
std::partial_sort(cur.begin(), cur.begin() + n_top, cur.end(),
1267+
[](const llama_token_data & a, const llama_token_data & b) {
1268+
return a.logit > b.logit;
1269+
});
1270+
}
12641271

12651272
// apply softmax
1266-
float max_l = cur[0].logit;
1273+
float max_l = -std::numeric_limits<float>::infinity();
1274+
if (n_top > 0) {
1275+
max_l = cur[0].logit; // partial_sort guarantees the absolute maximum is at index 0
1276+
} else {
1277+
for (const auto & t : cur) {
1278+
max_l = std::max(max_l, t.logit);
1279+
}
1280+
}
12671281
float cum_sum = 0.0f;
1268-
for (size_t i = 0; i < cur.size(); ++i) {
1269-
float p = expf(cur[i].logit - max_l);
1270-
cur[i].p = p;
1282+
for (auto & t : cur) {
1283+
float p = expf(t.logit - max_l);
1284+
t.p = p;
12711285
cum_sum += p;
12721286
}
1273-
for (size_t i = 0; i < cur.size(); ++i) {
1274-
cur[i].p /= cum_sum;
1287+
for (auto & t : cur) {
1288+
t.p /= cum_sum;
12751289
}
12761290

12771291
return cur;

tools/server/server-common.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ json format_response_rerank(
326326
// other utils
327327
//
328328

329-
std::vector<llama_token_data> get_token_probabilities(llama_context * ctx, int idx);
329+
std::vector<llama_token_data> get_token_probabilities(llama_context * ctx, int idx, size_t n_top);
330330

331331
std::string safe_json_to_str(const json & data);
332332

tools/server/server-context.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1824,8 +1824,7 @@ struct server_context_impl {
18241824
});
18251825
}
18261826
} else {
1827-
// TODO: optimize this with min-p optimization
1828-
std::vector<llama_token_data> cur = get_token_probabilities(ctx_tgt, idx);
1827+
std::vector<llama_token_data> cur = get_token_probabilities(ctx_tgt, idx, n_probs_request);
18291828
const size_t max_probs = cur.size();
18301829
const size_t n_probs = std::min(max_probs, n_probs_request);
18311830

0 commit comments

Comments
 (0)