ARTICLE · 1088723
TensorRT-LLM 0.5.0 源码之四十九
TensorRT-LLM 0.5.0 源码之四十九点个「赞」+「在看」❤️ 让我们知道这份文字有温暖到你,也是我们持续创作的最大动力! 推荐 TensorRT-LLM 0.5.0 源码之四十八 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显存,让大模型飞起来的核心技术 
TllmRuntime
class TllmRuntime{public: using TensorMap = StringPtrMap<ITensor>;explicit TllmRuntime(void const* engineData, std::size_t engineSize, nvinfer1::ILogger& logger);explicit TllmRuntime(nvinfer1::IHostMemory const& engineBuffer, nvinfer1::ILogger& logger) : TllmRuntime{engineBuffer.data(), engineBuffer.size(), logger} { }explicit TllmRuntime(void const* engineData, std::size_t engineSize);explicit TllmRuntime(nvinfer1::IHostMemory const& engineBuffer) : TllmRuntime{engineBuffer.data(), engineBuffer.size()} { } SizeType getNbContexts() const{ return static_cast<SizeType>(mContexts.size()); } nvinfer1::IExecutionContext& getContext(SizeType contextIndex) const{ return *mContexts.at(contextIndex); } SizeType getNbProfiles() const{ return static_cast<SizeType>(mEngine->getNbOptimizationProfiles()); } nvinfer1::IExecutionContext& addContext(std::int32_t profileIndex);void clearContexts();void setInputTensors(SizeType contextIndex, TensorMap const& tensorMap);void setOutputTensors(SizeType contextIndex, TensorMap& tensorMap);bool executeContext(SizeType contextIndex) const; CudaStream const& getStream() const; BufferManager::CudaStreamPtr getStreamPtr(){ return mStream; } nvinfer1::ICudaEngine& getEngine(){ return *mEngine; } nvinfer1::ICudaEngine const& getEngine() const{ return *mEngine; } BufferManager& getBufferManager(){ return mBufferManager; } BufferManager const& getBufferManager() const{ return mBufferManager; }private: BufferManager::CudaStreamPtr mStream; BufferManager mBufferManager; std::unique_ptr<nvinfer1::IRuntime> mRuntime; std::unique_ptr<nvinfer1::ICudaEngine> mEngine; BufferManager::IBufferPtr mEngineBuffer; std::vector<std::unique_ptr<nvinfer1::IExecutionContext>> mContexts; std::unique_ptr<ITensor> mDummyTensor;};TllmRuntime::TllmRuntime(void const* engineData, std::size_t engineSize, nvinfer1::ILogger& logger) : mStream(std::make_shared<CudaStream>()) , mBufferManager{mStream} , mRuntime{nvinfer1::createInferRuntime(logger)} , mEngine{mRuntime->deserializeCudaEngine(engineData, engineSize)}{ TLLM_CHECK_WITH_INFO(mEngine != nullptr, "Failed to deserialize cuda engine"); auto const devMemorySize = mEngine->getDeviceMemorySize(); mEngineBuffer = mBufferManager.gpu(devMemorySize);}TllmRuntime::TllmRuntime(void const* engineData, std::size_t engineSize) : TllmRuntime{engineData, engineSize, defaultLogger}{}CudaStream const& TllmRuntime::getStream() const{ return *mStream;}namespace{using DimType = std::remove_reference_t<decltype(std::declval<nvinfer1::Dims>().d[0])>;static_assert(sizeof(SizeType) >= sizeof(DimType), "SizeType is too small");static_assert(std::is_signed<SizeType>::value, "SizeType must be signed");nvinfer1::Dims shapeToDims(std::vector<std::size_t> const& shape){ TLLM_CHECK(shape.size() <= nvinfer1::Dims::MAX_DIMS); nvinfer1::Dims dims; auto constexpr dim_max = std::numeric_limits<DimType>::max(); dims.nbDims = static_cast<std::int32_t>(shape.size()); for (std::size_t i = 0; i < shape.size(); ++i) { // shape[i] >= 0 because it has unsigned type. Check upper bound: TLLM_CHECK(shape[i] <= static_cast<std::size_t>(dim_max)); dims.d[i] = static_cast<DimType>(shape[i]); } return dims;}std::vector<std::size_t> dimsToShape(nvinfer1::Dims const& dims){ TLLM_CHECK(dims.nbDims >= 0); std::vector<std::size_t> shape(dims.nbDims); for (std::int32_t i = 0; i < dims.nbDims; ++i) { TLLM_CHECK(dims.d[i] >= 0); shape[i] = static_cast<std::size_t>(dims.d[i]); } return shape;}tensorrt_llm::runtime::TllmLogger defaultLogger{};} // namespaceaddContext
nvinfer1::IExecutionContext& TllmRuntime::addContext(std::int32_t profileIndex){ TLLM_CHECK(0 <= profileIndex && profileIndex < mEngine->getNbOptimizationProfiles()); mContexts.emplace_back(mEngine->createExecutionContextWithoutDeviceMemory()); auto& context = *mContexts.back(); context.setDeviceMemory(mEngineBuffer->data()); context.setOptimizationProfileAsync(profileIndex, mStream->get()); return context;}clearContexts
void TllmRuntime::clearContexts(){ for (auto& context : mContexts) { context.reset(); } mContexts.clear();}executeContext
bool TllmRuntime::executeContext(SizeType contextIndex) const{ NVTX3_FUNC_RANGE(); auto& context = getContext(contextIndex); return context.enqueueV3(mStream->get());}setInputTensors
void TllmRuntime::setInputTensors(SizeType contextIndex, TensorMap const& tensorMap){ NVTX3_FUNC_RANGE(); TLLM_LOG_DEBUG("%s start", __PRETTY_FUNCTION__); auto& context = getContext(contextIndex); for (std::int32_t i = 0; i < mEngine->getNbIOTensors(); ++i) { auto const name = mEngine->getIOTensorName(i); if (mEngine->getTensorIOMode(name) == nvinfer1::TensorIOMode::kINPUT) { NVTX3_SCOPED_RANGE(input_tensor); auto pos = tensorMap.find(name); if (pos == tensorMap.end()) { auto expectedShape = mEngine->getTensorShape(name); TLLM_THROW( "Input tensor '%s' not found; expected shape: %s", name, ITensor::toString(expectedShape).c_str()); } auto const& tensor = pos->second; auto const tensorDtype = tensor->getDataType(); auto const engineDtype = mEngine->getTensorDataType(name); // WAR: TRT does not support mixed FP8 and FP16 input, so engine expects FP16 tensors. TLLM_CHECK_WITH_INFO(tensorDtype == engineDtype || (tensorDtype == nvinfer1::DataType::kFP8 && engineDtype == nvinfer1::DataType::kHALF), tc::fmtstr("%s: expected type %d, provided type %d", name, static_cast<std::int32_t>(engineDtype), static_cast<std::int32_t>(tensorDtype))); auto const shapeExpected = mEngine->getTensorShape(name); auto const shapeProvided = tensor->getShape(); TLLM_CHECK_WITH_INFO(shapeExpected.nbDims == shapeProvided.nbDims, tc::fmtstr("%s: expected %d dims, provided %d dims", name, shapeExpected.nbDims, shapeProvided.nbDims)); for (SizeType j = 0; j < shapeExpected.nbDims; ++j) { auto const dimExpected = shapeExpected.d[j]; auto const dimProvided = shapeProvided.d[j]; if (dimExpected >= 0 && dimExpected != dimProvided) { TLLM_LOG_WARNING( "%s: expected dim[%d] = %d, provided dim[%d] = %d", name, j, dimExpected, j, dimProvided); } } TLLM_CHECK_WITH_INFO(context.setInputShape(name, shapeProvided), name); auto* const data = tensor->data(); if (data) { context.setInputTensorAddress(name, data); } else { TLLM_CHECK_WITH_INFO(tensor->getSize() == 0, std::string("Invalid data for tensor: ") + name); // TensorRT runtime does not support nullptr. if (!mDummyTensor) { mDummyTensor = mBufferManager.gpu(ITensor::makeShape({1})); } context.setInputTensorAddress(name, mDummyTensor->data()); } } } { NVTX3_SCOPED_RANGE(infer_shapes); char const* missing; auto const nbMissing = context.inferShapes(1, &missing); if (nbMissing > 0) { TLLM_THROW("Input shape not specified: %s", missing); } else if (nbMissing < 0) { TLLM_THROW("Invalid input shape"); } } { NVTX3_SCOPED_RANGE(final_checks); TLLM_CHECK_WITH_INFO(context.allInputDimensionsSpecified(), "Input dimensions not specified"); TLLM_CHECK_WITH_INFO(context.allInputShapesSpecified(), "Input shapes not specified"); }}setOutputTensors
void TllmRuntime::setOutputTensors(SizeType contextIndex, TensorMap& tensorMap){ NVTX3_FUNC_RANGE(); auto& context = getContext(contextIndex); for (std::int32_t i = 0; i < mEngine->getNbIOTensors(); ++i) { auto const name = mEngine->getIOTensorName(i); if (mEngine->getTensorIOMode(name) == nvinfer1::TensorIOMode::kOUTPUT) { NVTX3_SCOPED_RANGE(output_tensor); auto const dims = context.getTensorShape(name); auto const engineDtype = mEngine->getTensorDataType(name); auto pos = tensorMap.find(name); if (pos != tensorMap.end()) { auto const& tensor = pos->second; auto const tensorDtype = tensor->getDataType(); // WAR: TRT does not support mixed FP8 and FP16 input, so engine expects FP16 tensors. TLLM_CHECK_WITH_INFO(tensorDtype == engineDtype || (tensorDtype == nvinfer1::DataType::kFP8 && engineDtype == nvinfer1::DataType::kHALF), tc::fmtstr("%s: expected type %d, provided type %d", name, static_cast<std::int32_t>(engineDtype), static_cast<std::int32_t>(tensorDtype))); tensor->reshape(dims); context.setTensorAddress(name, tensor->data()); } else { auto tensor = ITensor::SharedPtr(mBufferManager.gpu(dims, engineDtype)); tensorMap.insert(pos, std::make_pair(name, tensor)); context.setTensorAddress(name, tensor->data()); } } }}torch.h
class Torch{public:static at::Tensor tensor(ITensor::SharedPtr tensor){ auto const tensorOptions = at::device(TorchUtils::device((*tensor).data())) .pinned_memory((*tensor).getMemoryType() == MemoryType::kPINNED) .dtype(TorchUtils::dataType((*tensor).getDataType())) .layout(at::kStrided); return at::for_blob(tensor->data(), TorchUtils::shape(tensor->getShape())) // NOLINT(*-use-after-move) .options(tensorOptions) .deleter( [ptr = std::move(tensor)](void* data) mutable { try { TLLM_CHECK(data == ptr->data()); ptr.reset(); } catch (std::exception const& e) { TLLM_LOG_EXCEPTION(e); } }) .make_tensor(); }static at::Tensor buffer(IBuffer::SharedPtr buffer){ auto const shape = ITensor::makeShape({static_cast<runtime::SizeType>(buffer->getSize())}); return tensor(ITensor::view(std::move(buffer), shape)); }static void setCurrentStream(runtime::CudaStream& cudaStream){ at::cuda::setCurrentCUDAStream(TorchUtils::stream(cudaStream)); }private: Torch() = default;};torchUtils.h
class TorchUtils{public: using SizeType = at::IntArrayRef::value_type;static std::vector<SizeType> shape(ITensor::Shape const& dims){ TLLM_CHECK(dims.nbDims >= 0); std::vector<SizeType> shape{}; shape.reserve(dims.nbDims); std::transform( dims.d, dims.d + dims.nbDims, std::back_inserter(shape), [](auto x) { return static_cast<SizeType>(x); }); return shape; }static ITensor::Shape shape(at::IntArrayRef const& sizes){ TLLM_CHECK(sizes.size() <= ITensor::Shape::MAX_DIMS); ITensor::Shape shape{static_cast<runtime::SizeType>(sizes.size())}; using dimType = std::remove_reference_t<decltype(shape.d[0])>; for (std::size_t i = 0; i < sizes.size(); ++i) { TLLM_CHECK(sizes[i] <= std::numeric_limits<dimType>::max()); shape.d[i] = static_cast<dimType>(sizes[i]); } return shape; }static std::vector<SizeType> makeShape(std::initializer_list<runtime::SizeType> sizes){ return shape(ITensor::makeShape(sizes)); }static at::Device device(void const* ptr){ ::cudaPointerAttributes attr{}; TLLM_CUDA_CHECK(cudaPointerGetAttributes(&attr, ptr)); auto const memoryType = attr.type; return (memoryType == ::cudaMemoryTypeDevice || memoryType == ::cudaMemoryTypeManaged) ? at::Device{at::kCUDA, static_cast<at::DeviceIndex>(attr.device)} : at::Device{at::kCPU}; }static at::ScalarType dataType(IBuffer::DataType dataType){ switch (dataType) { case IBuffer::DataType::kFLOAT: return at::ScalarType::Float; case IBuffer::DataType::kHALF: return at::ScalarType::Half; case IBuffer::DataType::kINT8: return torch::kInt8; case IBuffer::DataType::kUINT8: return torch::kUInt8; case IBuffer::DataType::kINT32: return torch::kInt32; case IBuffer::DataType::kINT64: return torch::kInt64; case IBuffer::DataType::kBOOL: return at::ScalarType::Bool; case IBuffer::DataType::kFP8: return at::ScalarType::Bits8; case IBuffer::DataType::kBF16: return at::ScalarType::BFloat16; default: TLLM_THROW("unsupported data type"); } }static IBuffer::DataType dataType(at::ScalarType scalarType){ switch (scalarType) { case at::ScalarType::Float: return IBuffer::DataType::kFLOAT; case at::ScalarType::Half: return IBuffer::DataType::kHALF; case torch::kInt8: return IBuffer::DataType::kINT8; case torch::kUInt8: return IBuffer::DataType::kUINT8; case torch::kInt32: return IBuffer::DataType::kINT32; case torch::kInt64: return IBuffer::DataType::kINT64; case at::ScalarType::Bool: return IBuffer::DataType::kBOOL; case at::ScalarType::Bits8: return IBuffer::DataType::kFP8; case at::ScalarType::BFloat16: return IBuffer::DataType::kBF16; default: TLLM_THROW("unsupported data type"); } } static at::cuda::CUDAStream stream(runtime::CudaStream& cudaStream){ return at::cuda::getStreamFromExternal(cudaStream.get(), static_cast<at::DeviceIndex>(cudaStream.getDevice())); }private: TorchUtils() = default;};torchView.h
class TorchView : virtual public ITensor{public:static ITensor::UniquePtr of(at::Tensor&& tensor){ return ITensor::UniquePtr{new TorchView{std::move(tensor)}}; }static ITensor::UniquePtr of(at::Tensor tensor){ return ITensor::UniquePtr{new TorchView{std::move(tensor)}}; }void* data() override{ if (getSize() == 0) return nullptr; return mTensor.data_ptr(); } [[nodiscard]]void const* data() const override{ if (getSize() == 0) return nullptr; return mTensor.data_ptr(); } [[nodiscard]]size_t getSize() const override{ return mTensor.numel(); } [[nodiscard]] std::size_t getCapacity() const override{ return mCapacity; } [[nodiscard]] DataType getDataType() const override{ return TorchUtils::dataType(mTensor.scalar_type()); } [[nodiscard]] MemoryType getMemoryType() const override{ return mTensor.is_cuda() ? MemoryType::kGPU : mTensor.is_pinned() ? MemoryType::kPINNED : MemoryType::kCPU; }void resize(std::size_t newSize) override{ TLLM_CHECK(newSize <= getCapacity()); if (newSize != getSize()) { using dimType = std::remove_reference_t<decltype(mDims.d[0])>; auto constexpr max_size = std::numeric_limits<dimType>::max(); TLLM_CHECK_WITH_INFO(newSize <= max_size, "New size is too large. Use reshape() instead."); mTensor.resize_({static_cast<at::IntArrayRef::value_type>(newSize)}); mDims.nbDims = 1; mDims.d[0] = static_cast<dimType>(newSize); } }void release() override{ resize(0); } [[nodiscard]] Shape const& getShape() const override{ return mDims; }void reshape(Shape const& dims) override{ TLLM_CHECK(volumeNonNegative(dims) <= getCapacity()); mTensor.resize_(TorchUtils::shape(dims)); mDims = dims; }private:explicit TorchView(at::Tensor&& tensor) : mTensor(tensor) , mDims{TorchUtils::shape(mTensor.sizes())} , mCapacity{static_cast<std::size_t>(mTensor.numel())} { TLLM_CHECK(mTensor.is_contiguous()); }; at::Tensor mTensor; Shape mDims; std::size_t mCapacity;};参考文献
• https://github.com/NVIDIA/TensorRT-LLM/blob/release/0.5.0/cpp/tensorrt_llm/runtime/tllmRuntime.h
