Files
wehub-resource-sync 770d92cb1f
Lint / lint (push) Has been cancelled
Build Docs / Deploy Docs (push) Has been cancelled
Windows CI / Windows (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:23:58 +08:00

89 lines
3.1 KiB
C++

/*!
* Copyright (c) 2023-2025 by Contributors
* \file serve/engine_actions/auto_spec_decode.cc
*/
#include <numeric>
#include "../config.h"
#include "action.h"
namespace mlc {
namespace llm {
namespace serve {
/*!
* \brief The action that first makes a decision on whether to run speculative
* decoding or normal mode batch decode, and then runs the selected actions.
*/
class AutoSpecDecodeActionObj : public EngineActionObj {
public:
explicit AutoSpecDecodeActionObj(Array<EngineAction> spec_decode_actions,
Array<EngineAction> batch_decode_actions,
EngineConfig engine_config)
: spec_decode_actions_(std::move(spec_decode_actions)),
batch_decode_actions_(std::move(batch_decode_actions)),
engine_config_(std::move(engine_config)) {}
Array<Request> Step(EngineState estate) final {
int num_running_rsentries = estate->GetRunningRequestStateEntries().size();
if (num_running_rsentries == 0) {
return {};
}
// Calculate the draft length to use for the next round decode.
estate->spec_draft_length = CalculateDraftLength(estate, num_running_rsentries);
TVM_FFI_ICHECK_GE(estate->spec_draft_length, 0);
Array<Request> processed_requests;
// Use speculative decoding when the computed draft length is positive.
// Otherwise use normal mode batch decode.
Array<EngineAction> actions =
estate->spec_draft_length > 0 ? spec_decode_actions_ : batch_decode_actions_;
for (EngineAction action : actions) {
processed_requests = action->Step(estate);
}
// Reset the draft length.
estate->spec_draft_length = 0;
return processed_requests;
}
private:
int CalculateDraftLength(EngineState estate, int num_running_rsentries) {
// Right now we use the fixed table to select the draft length (only based on
// the batch size). We will follow up to adopt powerful draft length selection.
int draft_length = 0;
if (num_running_rsentries < 10) {
draft_length = 4;
} else if (num_running_rsentries < 20) {
draft_length = 3;
} else if (num_running_rsentries < 30) {
draft_length = 2;
} else {
draft_length = 0;
}
int effective_batch_size = num_running_rsentries * (draft_length + 1);
return effective_batch_size > engine_config_->max_num_sequence ? 0 : draft_length;
}
/*! \brief The speculative decode actions. */
Array<EngineAction> spec_decode_actions_;
/*! \brief The normal mode decode actions. */
Array<EngineAction> batch_decode_actions_;
/*! \brief The engine config. */
EngineConfig engine_config_;
};
EngineAction EngineAction::AutoSpecDecode(std::vector<EngineAction> spec_decode_actions_,
std::vector<EngineAction> batch_decode_actions_,
EngineConfig engine_config) {
return EngineAction(tvm::ffi::make_object<AutoSpecDecodeActionObj>(
Array<EngineAction>(spec_decode_actions_), Array<EngineAction>(batch_decode_actions_),
std::move(engine_config)));
}
} // namespace serve
} // namespace llm
} // namespace mlc