夜雨聆风学习资料网

ARTICLE · 1114540

TensorRT-LLM 0.5.0 源码之五十(完)

TensorRT-LLM 0.5.0 源码之五十(完)

iStatefulGptDecoder.h

Input

class Input{public:    using TensorPtr = std::shared_ptr<ITensor const>;explicit Input(TensorPtr logits)        : logits{std::move(logits)}    {        TLLM_CHECK_WITH_INFO(static_cast<bool>(this->logits), "Invalid logits tensor");    }    // mandatory parameters    TensorPtr logits; // [batchSize, maxBeamWidth, vocabSizePadded], on gpu    // parameters for beam search    TensorPtr cacheIndirection; // [batchSize, maxBeamWidth, maxSeqLen] - the k/v cache index for beam search, on gpu};

Output

class Output{public:    using TensorPtr = std::shared_ptr<ITensor>;    Output() = default;    // parameters for beam search    TensorPtr cacheIndirection; // [batchSize, maxBeamWidth, maxSeqLen], mandatory in beam search, on gpu    TensorPtr sequenceLengths;  // [batchSize, maxBeamWidth], mandatory, on gpu};

IStatefulGptDecoder

//! GPT decoder class with support for in-flight batchingclass IStatefulGptDecoder{public:    using CudaStreamPtr = std::shared_ptr<CudaStream>;    using TensorPtr = std::shared_ptr<ITensor>;    //! Setup the decoder before calling `forward()`, also calls reshapeBuffersvirtual void setup(        SizeType maxBatchSize, SizeType maxBeamWidth, SizeType maxSequenceLength, nvinfer1::DataType dtype)= 0;    //! @brief Initialize the decoder with new batch of inputs.virtual void newBatch(GenerationInput const& inputs, SamplingConfig const& samplingConfig)= 0;    //! @brief Run one step for all requests without blocking the host thread.virtual void forwardAsync(decoder::Output& output, decoder::Input const& input)= 0;    //! @brief Wait for the last call to `forwardAsync` to complete and return whether all sequences have finished.virtual bool isFinishedSync()= 0;    //! @brief Run one step for all requests.virtual bool forward(decoder::Output& output, decoder::Input const& input){        forwardAsync(output, input);        return isFinishedSync();    }    //! @brief Gather final results for all requests.virtual TensorPtr getFinalOutputIds() const= 0;    //! @returns [batchSize, beamWidth, maxSequenceLength], all token ids, on gpuvirtual TensorPtr getOutputIds() const= 0;    //! @returns [batchSize, beamWidth], latests generated tokens (per beam), on gpuvirtual TensorPtr getNewTokens() const= 0;    //! @returns [1], number of finished sequences, in pinned host memoryvirtual TensorPtr getNbFinished() const= 0;protected:    IStatefulGptDecoder() = default;};

StatefulGptDecoder

//! GPT decoder class with support for in-flight batchingclass StatefulGptDecoder : public IStatefulGptDecoder{public:    StatefulGptDecoder(std::size_t vocabSize, std::size_t vocabSizePadded, CudaStreamPtr stream);    //! Setup the decoder before calling `forward()`void setup(        SizeType maxBatchSize, SizeType maxBeamWidth, SizeType maxSequenceLength, nvinfer1::DataType dtype) override;    //! @brief Initialize the decoder with new batch of inputs.void newBatch(GenerationInput const& input, SamplingConfig const& samplingConfig) override;void forwardAsync(decoder::Output& output, decoder::Input const& input) override;bool isFinishedSync() override;    //! @brief Gather final results for all requests.    [[nodiscard]] TensorPtr getFinalOutputIds() const override;    //! @returns [batchSize, maxBeamWidth, maxInputLength + maxNewTokens], contains input token ids and generated token    //! ids without padding, on gpu    [[nodiscard]] TensorPtr getOutputIds() const override{        return mDecodingOutput->ids;    }    //! @returns [batchSize, maxBeamWidth], tokens generated in last forward pass, on gpu    [[nodiscard]] TensorPtr getNewTokens() const override{        return mDecodingOutput->newTokens;    }    //! @returns [1], number of finished sequences, in pinned host memory    [[nodiscard]] TensorPtr getNbFinished() const override{        return mDecodingOutput->finishedSum;    }private:void reshapeBuffers(SizeType batchSize, SizeType beamWidth, SizeType maxSequenceLength);private:    std::size_t const mVocabSize;    std::size_t const mVocabSizePadded;    CudaStreamPtr mStream;    BufferManager mBufferManager;    using GptDecoderPtr = std::unique_ptr<IGptDecoder>;    GptDecoderPtr mDecoder;    using DecodingInputPtr = std::unique_ptr<DecodingInput>;    DecodingInputPtr mDecodingInput;    using DecodingOutputPtr = std::unique_ptr<DecodingOutput>;    DecodingOutputPtr mDecodingOutput;    CudaEvent mDecodedEvent{};    SizeType mNbSteps;    SizeType mMaxSequenceLength{};    SizeType mMaxNewTokens;};
StatefulGptDecoder::StatefulGptDecoder(std::size_t vocabSize, std::size_t vocabSizePadded, CudaStreamPtr stream)    : mVocabSize{vocabSize}    , mVocabSizePadded{vocabSizePadded}    , mStream{std::move(stream)}    , mBufferManager{mStream}{    TLLM_LOG_DEBUG("%s start", __PRETTY_FUNCTION__);    auto constexpr nvTokenIdType = TRTDataType<TokenIdType>::value;    auto constexpr nvSizeType = TRTDataType<SizeType>::value;    auto constexpr nvFloatType = TRTDataType<float>::value;    auto& dInput = mDecodingInput;    auto dummyLogits = mBufferManager.emptyTensor(MemoryType::kGPU, nvFloatType);    auto endIds = mBufferManager.emptyTensor(MemoryType::kGPU, nvTokenIdType);    dInput = std::make_unique<DecodingInput>(0, 0, std::move(dummyLogits), std::move(endIds));    dInput->sequenceLimitLength = mBufferManager.emptyTensor(MemoryType::kGPU, nvSizeType);    dInput->lengths = mBufferManager.emptyTensor(MemoryType::kGPU, nvSizeType);    auto& dOutput = mDecodingOutput;    auto outputIds = mBufferManager.emptyTensor(MemoryType::kGPU, nvTokenIdType);    dOutput = std::make_unique<DecodingOutput>(std::move(outputIds));    dOutput->newTokens = mBufferManager.emptyTensor(MemoryType::kGPU, nvTokenIdType);    dOutput->parentIds = mBufferManager.emptyTensor(MemoryType::kGPU, nvTokenIdType);    dOutput->finished = mBufferManager.emptyTensor(MemoryType::kGPU, TRTDataType<bool>::value);    dOutput->finishedSum = BufferManager::pinned(ITensor::makeShape({1}), nvSizeType);    dOutput->lengths = mBufferManager.emptyTensor(MemoryType::kGPU, nvSizeType);    dOutput->cumLogProbs = mBufferManager.emptyTensor(MemoryType::kGPU, nvFloatType);    dOutput->beamHypotheses.empty(mBufferManager);    TLLM_LOG_DEBUG("%s stop", __PRETTY_FUNCTION__);}

setup

void StatefulGptDecoder::setup(    SizeType maxBatchSize, SizeType maxBeamWidth, SizeType maxSequenceLength, nvinfer1::DataType dtype){    TLLM_LOG_DEBUG("%s start", __PRETTY_FUNCTION__);    mDecoder = IGptDecoder::create(dtype, mVocabSize, mVocabSizePadded, mStream);    reshapeBuffers(maxBatchSize, maxBeamWidth, maxSequenceLength);    TLLM_LOG_DEBUG("%s stop", __PRETTY_FUNCTION__);}

reshapeBuffers

void StatefulGptDecoder::reshapeBuffers(SizeType batchSize, SizeType beamWidth, SizeType maxSequenceLength){    TLLM_LOG_DEBUG("%s start", __PRETTY_FUNCTION__);    TLLM_CHECK(batchSize > 0);    TLLM_CHECK(beamWidth > 0);    TLLM_CHECK(maxSequenceLength > 0);    mMaxSequenceLength = maxSequenceLength;    auto const batchSizeShape = ITensor::makeShape({batchSize});    auto const batchSizeXbeamWidth = ITensor::makeShape({batchSize, beamWidth});    auto& dInput = *mDecodingInput;    const_cast<ITensor&>(*dInput.endIds).reshape(batchSizeXbeamWidth);    auto& sequenceLimitLength = const_cast<ITensor&>(*dInput.sequenceLimitLength);    sequenceLimitLength.reshape(batchSizeShape);    kernels::invokeFill(sequenceLimitLength, mMaxSequenceLength, *mStream);    auto& inputLengths = const_cast<ITensor&>(*dInput.lengths);    inputLengths.reshape(batchSizeXbeamWidth);    mBufferManager.setZero(inputLengths);    auto const outputIdsShape = ITensor::makeShape({batchSize, beamWidth, maxSequenceLength});    auto& dOutput = *mDecodingOutput;    dOutput.ids->reshape(outputIdsShape);    dOutput.newTokens->reshape(batchSizeXbeamWidth);    mBufferManager.setZero(*dOutput.newTokens);    dOutput.parentIds->reshape(outputIdsShape);    dOutput.finished->reshape(batchSizeXbeamWidth);    mBufferManager.setZero(*dOutput.finished);    mBufferManager.setZero(*dOutput.finishedSum);    if (beamWidth > 1)    {        dOutput.cumLogProbs->reshape(batchSizeXbeamWidth);        mBufferManager.setZero(*dOutput.cumLogProbs);        dOutput.beamHypotheses.reshape(batchSize, beamWidth, mMaxSequenceLength);    }    else    {        dOutput.beamHypotheses.release();    }    mMaxNewTokens = 0;    mNbSteps = 0;    TLLM_LOG_DEBUG("%s stop", __PRETTY_FUNCTION__);}

initOutputIds

void initOutputIds(TensorPtr const& outputIds, TensorPtr const& inputIds, TensorPtr const& inputLengths,    TensorPtr const& inputOffsets, SizeType const padId, SizeType const endId, SizeType const maxInputLength,    bool const inputPacked, CudaStream const& stream){    TLLM_LOG_DEBUG("%s start", __PRETTY_FUNCTION__);    kernels::invokeFill(*outputIds, endId, stream);    if (inputPacked)    {        kernels::invokeCopyPackedInputToOutput(*outputIds, *inputIds, *inputOffsets, maxInputLength, padId, stream);    }    else    {        kernels::invokeCopyInputToOutput(*outputIds, *inputIds, *inputLengths, padId, stream);    }    TLLM_LOG_DEBUG("%s stop", __PRETTY_FUNCTION__);}

newBatch

void StatefulGptDecoder::newBatch(GenerationInput const& inputs, SamplingConfig const& samplingConfig){    TLLM_LOG_DEBUG("%s start", __PRETTY_FUNCTION__);    auto& manager = mBufferManager;    auto& stream = mStream;    auto const inputLengths = inputs.lengths;    auto const& inputLengthsShape = inputLengths->getShape();    auto const batchSize = inputLengthsShape.d[0];    auto const beamWidth = samplingConfig.beamWidth;    reshapeBuffers(batchSize, beamWidth, mMaxSequenceLength);    mDecoder->setup(samplingConfig, batchSize);    // sanity checks, should always be true after reshape    auto const& outputIdsShape = mDecodingOutput->ids->getShape();    auto const maxBatchSize = outputIdsShape.d[0];    TLLM_CHECK(batchSize == maxBatchSize);    auto const maxBeamWidth = outputIdsShape.d[1];    TLLM_CHECK(beamWidth == maxBeamWidth);    auto const& inputIds = inputs.ids;    auto const inputLengthsHost = manager.copyFrom(*inputLengths, MemoryType::kCPU);    auto const* inputLengthsData = bufferCast<SizeType>(*inputLengthsHost);    SizeType const maxInputLength = *std::max_element(inputLengthsData, inputLengthsData + inputLengths->getSize());    TensorPtr inputOffsets = manager.emptyTensor(MemoryType::kGPU, TRTDataType<SizeType>::value);    if (inputs.packed)    {        inputOffsets->reshape(ITensor::makeShape({batchSize + 1}));        manager.setZero(*inputOffsets);        kernels::invokeInclusiveSum(*ITensor::slice(inputOffsets, 1), *inputLengths, manager, *stream);    }    mMaxNewTokens = inputs.maxNewTokens.value_or(mMaxSequenceLength - maxInputLength);    TLLM_CHECK_WITH_INFO(maxInputLength + mMaxNewTokens <= mMaxSequenceLength,        tc::fmtstr("Input length (%d) + max new tokens (%d) must be less than max sequence length (%d).",            maxInputLength, mMaxNewTokens, mMaxSequenceLength));    TLLM_CHECK(inputIds->getDataType() == TRTDataType<TokenIdType>::value);    auto const endId = inputs.endId;    auto const padId = inputs.padId;    // inputs    auto& dInput = *mDecodingInput;    dInput.maxLength = maxInputLength;    dInput.batchSize = batchSize;    kernels::invokeFill(const_cast<ITensor&>(*dInput.endIds), endId, *stream);    dInput.embeddingBias = inputs.embeddingBiasOpt;    dInput.badWordsList = inputs.badWordsList;    dInput.stopWordsList = inputs.stopWordsList;    kernels::invokeFill(const_cast<ITensor&>(*dInput.sequenceLimitLength), mMaxSequenceLength, *stream);    auto inputLengthsView = ITensor::view(dInput.lengths, ITensor::makeShape({batchSize * beamWidth}));    kernels::tileTensor(const_cast<ITensor&>(*inputLengthsView), *inputLengths, beamWidth, *stream);    // output    auto& dOutput = *mDecodingOutput;    manager.setZero(*dOutput.newTokens);    manager.setZero(*dOutput.finished);    manager.setZero(*dOutput.finishedSum);    if (beamWidth > 1)    {        std::vector<float> cumLogProbsHost(batchSize * beamWidth, DecodingOutput::kNegativeInfinity);        // Set the entries for the first beam to 0        for (SizeType i = 0; i < batchSize; ++i)        {            cumLogProbsHost[tc::flat_index2(i, 0, beamWidth)] = 0;        }        manager.copy(cumLogProbsHost.data(), *dOutput.cumLogProbs);        // kernels::invokeFill(*dOutput.cumLogProbs, DecodingOutput::kNegativeInfinity, *stream);        // for (SizeType batchIdx = 0; batchIdx < batchSize; ++batchIdx)        // {        //     auto cumLogProbsSlice = ITensor::slice(dOutput.cumLogProbs, batchIdx, 1);        //     manager.setZero(*IBuffer::slice(cumLogProbsSlice, 0, 1));        // }        manager.setZero(*dOutput.parentIds);        dOutput.beamHypotheses.init(manager, endId);    }    else    {        // manager.setZero(*dOutput.cumLogProbs);    }    // copy the request ids into dOutput.ids (with tiling)    initOutputIds(        dOutput.ids, inputIds, inputLengths, inputOffsets, padId, endId, maxInputLength, inputs.packed, *stream);    // remaining    mNbSteps = 0;    TLLM_LOG_DEBUG("%s stop", __PRETTY_FUNCTION__);}

forwardAsync

void StatefulGptDecoder::forwardAsync(decoder::Output& output, decoder::Input const& input){    TLLM_LOG_DEBUG("%s start", __PRETTY_FUNCTION__);    auto& logits = input.logits;    auto const& logitsShape = logits->getShape();    auto const& outputIdsShape = mDecodingOutput->ids->getShape();    auto const batchSize = outputIdsShape.d[0];    TLLM_CHECK(logitsShape.d[0] == batchSize);    auto const maxBeamWidth = outputIdsShape.d[1];    TLLM_CHECK(logitsShape.d[1] == maxBeamWidth);    TLLM_CHECK(static_cast<std::size_t>(logitsShape.d[2]) == mVocabSizePadded);    auto& srcCacheIndirection = input.cacheIndirection;    auto& tgtCacheIndirection = output.cacheIndirection;    TLLM_CHECK_WITH_INFO((srcCacheIndirection && tgtCacheIndirection) || (!srcCacheIndirection && !tgtCacheIndirection),        "Specify both srcCacheIndirection and tgtCacheIndirection or neither.");    TLLM_CHECK(!srcCacheIndirection || srcCacheIndirection->getDataType() == TRTDataType<SizeType>::value);    TLLM_CHECK(!tgtCacheIndirection || tgtCacheIndirection->getDataType() == TRTDataType<SizeType>::value);    auto& dInput = *mDecodingInput;    auto& dOutput = *mDecodingOutput;    dInput.logits = logits;    if (srcCacheIndirection && tgtCacheIndirection)    {        dInput.cacheIndirection = srcCacheIndirection;        dOutput.cacheIndirection = tgtCacheIndirection;    }    dOutput.lengths = output.sequenceLengths;    mDecoder->forwardAsync(dOutput, dInput);    mStream->record(mDecodedEvent.get());    dInput.step += 1;    mNbSteps += 1;    TLLM_LOG_DEBUG("%s stop", __PRETTY_FUNCTION__);}

isFinishedSync

bool StatefulGptDecoder::isFinishedSync(){    TLLM_LOG_DEBUG("%s start", __PRETTY_FUNCTION__);    mDecodedEvent.synchronize();    auto& dOutput = *mDecodingOutput;    auto finished = mNbSteps >= mMaxNewTokens        // This condition requires the synchronization above        || *bufferCast<SizeType>(*dOutput.finishedSum) == static_cast<SizeType>(dOutput.finished->getSize());    TLLM_LOG_DEBUG("%s stop", __PRETTY_FUNCTION__);    return finished;}

getFinalOutputIds

IStatefulGptDecoder::TensorPtr StatefulGptDecoder::getFinalOutputIds() const{    // TODO (rkobus) can we do this inplace?    TLLM_LOG_DEBUG("%s start", __PRETTY_FUNCTION__);    auto& outputIds = mDecodingOutput->ids;    auto finalOutputIds = mBufferManager.gpu(outputIds->getShape(), outputIds->getDataType());    IGptDecoder::gatherTree(*finalOutputIds, *mDecodingOutput, *mDecodingInput, mBufferManager);    mBufferManager.copy(*finalOutputIds, *outputIds);    TLLM_LOG_DEBUG("%s stop", __PRETTY_FUNCTION__);    return outputIds;}

参考文献

  • • https://github.com/NVIDIA/TensorRT-LLM/blob/release/0.5.0/cpp/include/tensorrt_llm/runtime/iStatefulGptDecoder.h
  • • https://github.com/NVIDIA/TensorRT-LLM/blob/release/0.5.0/cpp/tensorrt_llm/runtime/statefulGptDecoder.h
点个「赞」+「在看」❤️
让我们知道这份文字有温暖到你,也是我们持续创作的最大动力!
推荐
什么是智能体驾驭框架(Agent Harness)?
SGLang-Omni 通俗解析(七):API Server——工厂的对外营业大厅
TensorRT-LLM 0.5.0 源码之四十九
SGLang-Omni 通俗解析(六):新 TTS 车间入驻指南与血泪避坑手册
DALI Audio Resample
把"炼丹炉"直播给你看:小米 MiMo-V2.6-Pro/Flash 强化学习训练全景解读
全双工语音模型究竟为语音AI带来了哪些变革
SGLang-Omni 通俗解析(五):厂内物流与通信——对讲机只管喊话,物流只管搬货
Moshi:面向实时对话的语音‑文本基础模型
线程别名
Claude Fable 5:自改进智能体——14步循环工程指南
MOSS Transcribe Diarize 技术报告
SGLang-Omni 通俗解析(四):流水线"四大金刚"与反馈循环黑科技
京东大溶洞
SGLang-Omni 通俗解析(三):一个请求的奇幻漂流——架构全景
SGLang-Omni 通俗解析(二):进程命名潜规则与5个高级机制
Qwen3-Omni 技术报告
SGLang-Omni 通俗解析(一):用"开工厂"的思路理解多模态配置
权限、沙箱与自主智能体
技能:规定智能体应该如何思考
循环工程:设计编码代理系统,而不是每次都手动提示
VoxCPM2 技术报告
Agent 数据生产与训练
什么是循环工程?AI 编码智能体的新范式
从空文件夹到生成图表:Claude Code 实战教程
Claude Code 入门:研究者配置指南
GLM-5.2:面向长时序任务打造
循环工程(Loop Engineering)
Agent SFT 标准数据格式 + Loss Mask 完整实现
4D Parallelism
TileLang与OpenAI Triton的核心区别
Agent SFT 数据
Claude Code 的上限,就是你的上限
如何用Claude Code提升软件工程工作效率、改善生活
LLM推理优化的核心技术:深入理解KV缓存与分页注意力机制
Qwen3-TTS 技术报告
PagedAttention
如何让AI听懂你的“话外音”?GOAT-SLM模型实现更懂情感的语言交互
FlashAttention与PagedAttention详解:拯救GPU显存,让大模型飞起来的核心技术

相关学习资料