안녕하세요.
GPU를 MFC에서 사용하며 ONNX를 사용하려고 하다가
속도 이슈 때문에 TensorRT를 알아보고 있습니다.
Onnx파일을 파싱하여 인퍼런스하는 샘플을 보고
trtexec로 엔진 파일을 작성 하여 엔진파일을 이용해 c++에서 추론에 사용하고 싶습니다.
예제가 파이썬밖에 잘 없던데 혹시 아시는 분(혹은GPT) 계신가요?
- 아래 답변은 OpenAI의 GPT-3.5(ChatGPT) 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
- 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다.
안녕하세요. TensorRT C++에서 엔진 파일을 로딩하여 추론하는 방법에 대해 설명드리겠습니다.
TensorRT C++에서 엔진 파일을 로딩하여 추론하는 방법은 다음과 같습니다.
-
TensorRT 엔진 파일 생성하기
- TensorRT 엔진 파일은 TensorRT Python API를 사용하여 생성할 수 있습니다.
- TensorRT Python API를 사용하여 엔진 파일을 생성하는 방법은 다음과 같습니다.
import tensorrt as trt # TensorRT 엔진 파일 생성을 위한 Builder 생성 builder = trt.Builder(TRT_LOGGER) # ONNX 모델 파싱 explicit_batch = 1 << (int)(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH) network = builder.create_network(explicit_batch) parser = trt.OnnxParser(network, TRT_LOGGER) with open(onnx_model_path, 'rb') as model: parser.parse(model.read()) # TensorRT 엔진 파일 생성 engine = builder.build_cuda_engine(network) with open(engine_file_path, "wb") as f: f.write(engine.serialize())
-
TensorRT 엔진 파일 로딩하기
- TensorRT 엔진 파일을 로딩하기 위해서는
IRuntime
인터페이스를 사용합니다. IRuntime
인터페이스를 사용하여 엔진 파일을 로딩하는 방법은 다음과 같습니다.
#include <NvInferRuntimeCommon.h> // TensorRT 엔진 파일 로딩 std::ifstream engine_file(engine_file_path, std::ios::binary); engine_file.seekg(0, std::ios::end); const size_t engine_size = engine_file.tellg(); engine_file.seekg(0, std::ios::beg); std::vector<char> engine_data(engine_size); engine_file.read(engine_data.data(), engine_size); nvinfer1::IRuntime* runtime = nvinfer1::createInferRuntime(gLogger); nvinfer1::ICudaEngine* engine = runtime->deserializeCudaEngine(engine_data.data(), engine_size, nullptr);
- TensorRT 엔진 파일을 로딩하기 위해서는
-
TensorRT 엔진 파일을 사용하여 추론하기
- TensorRT 엔진 파일을 사용하여 추론하기 위해서는
IExecutionContext
인터페이스를 사용합니다. IExecutionContext
인터페이스를 사용하여 추론하는 방법은 다음과 같습니다.
#include <NvInferRuntimeCommon.h> // TensorRT 엔진 파일을 사용하여 추론 nvinfer1::IExecutionContext* context = engine->createExecutionContext(); context->execute(batch_size, bindings);
- TensorRT 엔진 파일을 사용하여 추론하기 위해서는
위의 코드에서 engine_file_path
는 TensorRT 엔진 파일의 경로를, batch_size
는 추론할 배치 크기를, bindings
는 입력 및 출력 바인딩 정보를 나타내는 std::vector<void*>
입니다.
TensorRT C++에서 엔진 파일을 로딩하여 추론하는 방법에 대해 설명드렸습니다. 참고하시길 바랍니다.
- 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래
를 한 번 눌러주시길 부탁드려요!
- 아래 답변은 OpenAI의 GPT-4 모델로 자동 생성한 것으로, 정확하지 않을 수 있습니다.
- 잘못된 답변을 보셨다면 댓글로 첨삭 지도 부탁드립니다.
안녕하세요!
TensorRT를 사용하여 ONNX 모델을 엔진 파일로 변환하고, C++에서 엔진 파일을 로드하여 추론하는 예제를 설명드리겠습니다.
먼저, TensorRT에서 ONNX 모델을 엔진 파일로 변환하는 과정은 다음과 같습니다.
- ONNX 모델을 TensorRT 빌더로 로드합니다.
- 최적화 옵션을 설정하고, 엔진을 빌드합니다.
- 빌드된 엔진을 파일로 저장합니다.
이제 C++에서 TensorRT 엔진 파일을 로드하고 추론하는 과정은 다음과 같습니다.
- TensorRT 런타임을 생성합니다.
- 저장된 엔진 파일을 불러옵니다.
- 런타임에서 엔진을 디-시리얼라이즈합니다.
- 엔진에서 실행 컨텍스트를 생성하고, 입력 및 출력 버퍼를 설정합니다.
- 추론을 실행하고 결과를 얻습니다.
예제 코드는 아래와 같습니다.
#include <iostream>
#include <fstream>
#include <NvInfer.h>
#include <NvOnnxParser.h>
#include <cuda_runtime_api.h>
using namespace nvinfer1;
int main() {
// 1. TensorRT 런타임 생성
IRuntime* runtime = createInferRuntime(gLogger);
// 2. 저장된 엔진 파일 불러오기
std::ifstream engineFile("your_engine_file.trt", std::ios::binary);
if (!engineFile) {
std::cerr << "Failed to open engine file." << std::endl;
return 1;
}
engineFile.seekg(0, engineFile.end);
size_t engineSize = engineFile.tellg();
engineFile.seekg(0, engineFile.beg);
std::vector<char> engineData(engineSize);
engineFile.read(engineData.data(), engineSize);
engineFile.close();
// 3. 런타임에서 엔진 디-시리얼라이즈
ICudaEngine* engine = runtime->deserializeCudaEngine(engineData.data(), engineSize, nullptr);
// 4. 엔진에서 실행 컨텍스트 생성 및 입력/출력 버퍼 설정
IExecutionContext* context = engine->createExecutionContext();
int inputIndex = engine->getBindingIndex("input_tensor_name");
int outputIndex = engine->getBindingIndex("output_tensor_name");
float* inputBuffer;
float* outputBuffer;
cudaMalloc(&inputBuffer, batchSize * inputSize * sizeof(float));
cudaMalloc(&outputBuffer, batchSize * outputSize * sizeof(float));
// 5. 추론 실행 및 결과 얻기
void* buffers[] = {inputBuffer, outputBuffer};
cudaMemcpy(inputBuffer, inputData, batchSize * inputSize * sizeof(float), cudaMemcpyHostToDevice);
context->execute(batchSize, buffers);
cudaMemcpy(outputData, outputBuffer, batchSize * outputSize * sizeof(float), cudaMemcpyDeviceToHost);
// 메모리 해제 및 종료
cudaFree(inputBuffer);
cudaFree(outputBuffer);
context->destroy();
engine->destroy();
runtime->destroy();
return 0;
}
위 예제에서 your_engine_file.trt
는 TensorRT로 변환한 엔진 파일의 경로이며, input_tensor_name
과 output_tensor_name
은 ONNX 모델의 입력 및 출력 텐서 이름입니다. 또한, inputData
와 outputData
는 입력 및 출력 데이터를 저장할 호스트 메모리 포인터입니다.
이 예제를 사용하여 TensorRT 엔진 파일을 로드하고 추론을 실행할 수 있습니다. 추가적인 정보가 필요하시면, 공식 TensorRT 문서를 참조하시기 바랍니다: TensorRT Developer Guide
- 답변이 어떠셨나요? 괜찮았다고 생각하신다면 아래
를 한 번 눌러주시길 부탁드려요!
결국 해결했습니다.
일단 아이디어는 sample ONNX MNIST 예제가 있어서
거기서 Onnx를 로딩하는 engine을 tensorRT engine file을 로딩하여 대체하는 것이었습니다.
그러면 기타 다른 기능은 예제 그대로 가져 갈 수 있었으니까요.
수정하면서 onnx 파일에서 network 구조를 뽑아서 input, output의 사이즈를 체크하는 부분이
Build 맨 밑에 있는데, 그 관련된 것이 infer 함수 내에도 있어서
dim을 불러오던것을 상수로 바꿔주고 (입력 28x28 출력 10)
엔진 파일을 로딩해주니 onnx 파일 없이도 잘 돌아가는군요!!