exclude first generated token

This commit is contained in:
Xuan Son Nguyen
2026-08-12 12:01:01 +02:00
parent a2fd44e35f
commit 20ce126733
2 changed files with 24 additions and 9 deletions
+14 -5
View File
@@ -389,13 +389,19 @@ struct server_slot_stats {
return std::max<int64_t>(1, t_gen_last - t_prompt_last) / 1000.0;
}
// number of decode steps spent on generation
// the first token is free, it comes from the logits of the last prompt batch
uint64_t n_gen_steps() const {
return n_predict > 0 ? n_predict - 1 : 0;
}
// other derived metrics
// note: all of them return 0.0 if the divisor is not known yet
double t_prompt_per_token_ms() const {
return n_prompt_processed > 0 ? t_prompt_ms() / n_prompt_processed : 0.0;
}
double t_gen_per_token_ms() const {
return n_predict > 0 ? t_gen_ms() / n_predict : 0.0;
return n_gen_steps() > 0 ? t_gen_ms() / n_gen_steps() : 0.0;
}
double n_prompt_tps() const {
const double t_ms = t_prompt_ms();
@@ -403,7 +409,7 @@ struct server_slot_stats {
}
double n_gen_tps() const {
const double t_ms = t_gen_ms();
return t_ms > 0.0 ? 1e3 / t_ms * n_predict : 0.0;
return t_ms > 0.0 ? 1e3 / t_ms * n_gen_steps() : 0.0;
}
// false if the slot never started, i.e. the task result carries no stats
@@ -420,15 +426,18 @@ struct server_metrics {
int64_t t_start = 0;
struct bucket {
uint64_t count = 0;
uint64_t count = 0; // number of tokens
uint64_t steps = 0; // number of decode steps, differs from count for generation
uint64_t time = 0; // in milliseconds
// the rate uses the decode steps, so that free tokens do not inflate it
double n_per_second() const {
return time > 0 ? (double) count / (double) time * 1e3 : 0.0;
return time > 0 ? (double) steps / (double) time * 1e3 : 0.0;
}
void add(uint64_t n, double t_ms) {
void add(uint64_t n, uint64_t n_steps, double t_ms) {
count += n;
steps += n_steps;
time += (uint64_t) t_ms;
}
};
+10 -4
View File
@@ -787,8 +787,11 @@ struct server_slot {
void server_metrics::on_prompt_eval(const server_slot & slot) {
const double t_ms = slot.stats.t_prompt_ms();
prompt .add(slot.stats.n_prompt_processed, t_ms);
prompt_bucket.add(slot.stats.n_prompt_processed, t_ms);
// every prompt token needs one decode step
const uint64_t n = slot.stats.n_prompt_processed;
prompt .add(n, n, t_ms);
prompt_bucket.add(n, n, t_ms);
n_tokens_max = std::max(n_tokens_max, (uint64_t) slot.prompt.n_tokens());
}
@@ -796,8 +799,11 @@ void server_metrics::on_prompt_eval(const server_slot & slot) {
void server_metrics::on_prediction(const server_slot & slot) {
const double t_ms = slot.stats.t_gen_ms();
predict .add(slot.stats.n_predict, t_ms);
predict_bucket.add(slot.stats.n_predict, t_ms);
const uint64_t n = slot.stats.n_predict;
const uint64_t n_steps = slot.stats.n_gen_steps();
predict .add(n, n_steps, t_ms);
predict_bucket.add(n, n_steps, t_ms);
n_draft_tokens += slot.stats.n_draft_tokens;
n_draft_accepted += slot.stats.n_draft_accepted;