the output of onnx model is different from model inferenced by TensorRT
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 13.4k
- Forks
- 2.4k
- Avg merge
- 5d 3h
- Merged PRs (30d)
- 2
Description
Description
I attempted to compile a Hugging Face model (the Hugging Face model link is: https://huggingface.co/OpenGVLab/InternViT-6B-448px-V1-5, which includes both the model architecture code and model files) using TensorRT (TRT) to improve inference speed. The steps I followed are hf -> onnx -> trt.
I performed inference on the same image using Hugging Face (hf), ONNX, and TRT engine. I found that the inference results from hf and ONNX were consistent, but the TRT engine's result was different from the former two.
I would like to know why the ONNX results are correct, but the inference results from the engine compiled with trtexec are wrong. Why is this happening?
The conversion code from hf to ONNX is:
import torch
from transformers import AutoModel
from typing import List,Dict
import time
import os
import warnings
class InternVL2VisionWrapper(torch.nn.Module):
def __init__(self, model, ):
super().__init__()
self.model = model
def forward(self, pixel_values):
features = self.model(pixel_values).last_hidden_state
return features
model_path="/media/star/disk2/pretrained_model/InternViT/InternViT-6B-448px-V1-5"
output_dir="/media/star/8T/tmp/InternViT-6B-448px-V1-5/onnx"
os.makedirs(f'{output_dir}', exist_ok=True)
model = AutoModel.from_pretrained(
model_path,
torch_dtype=torch.float16,
low_cpu_mem_usage=True,
trust_remote_code=True).cuda().eval()
device = torch.device("cuda") if torch.cuda.is_available() else "cpu"
wrapper = InternVL2VisionWrapper(model=model.to(device))
dummy_image = torch.empty(1,
3,
448,
448,
dtype=torch.float16,
device=device) # dummy image
def export_visual_wrapper_onnx(visual_wrapper,
input,
output_dir,
input_names=['input'],
dynamic_axes={'input': {0: 'batch'}, 'output': {0: 'batch'}}
):
torch.onnx.export(visual_wrapper,
input,
f'{output_dir}/visual_encoder.onnx',
opset_version=17,
input_names=input_names,
output_names=['output'],
dynamic_axes=dynamic_axes)
export_visual_wrapper_onnx(wrapper, dummy_image, output_dir)
The conversion code from ONNX to TRT engine is:
MODEL_NAME="InternVL2-40B"
OUTPUT_MODEL_NAME="InternVL2_40B"
onnx_process_version="onnx_v1"
max_batch_size=24
onnx_dtype="float16"
trt_dtype="best"
/usr/src/tensorrt/bin/trtexec \
--onnx=/data/eas/visual_engine/a100/InternViT-6B-448px-V1-5/onnx/visual_encoder.onnx \
--saveEngine=/data/eas/visual_engine/a100/InternViT-6B-448px-V1-5/visual_encoder.trtexec.${trt_dtype}.maxBatchSize${max_batch_size}.engine \
--minShapes=input:1x3x448x448 \
--optShapes=input:8x3x448x448 \
--maxShapes=input:24x3x448x448 \
--best
The inference code for hf is:
import torch
import time
from transformers import AutoModel, CLIPImageProcessor
import numpy as np
model_path="/media/star/disk2/pretrained_model/InternViT/InternViT-6B-448px-V1-5"
torch_dtype=torch.float16
model = AutoModel.from_pretrained(
model_path,
torch_dtype=torch_dtype,
low_cpu_mem_usage=True,
trust_remote_code=True).cuda().eval()
pixel_values = torch.tensor(np.load("/media/star/8T/tmp/internvn2_40b_image2_patch1.npy")).to(torch_dtype).cuda()
print(f"pixel_values.shape={pixel_values.shape}")
pixel_values=torch.concat([pixel_values], dim=0)
start_time=time.time()
outputs = model(pixel_values)
print(f"run time is {time.time()-start_time} seconds")
print(f"outputs.last_hidden_state={outputs.last_hidden_state}")
print(f"outputs.last_hidden_state.shape={outputs.last_hidden_state.shape}")
The inference code for ONNX is:
import os
import torch
import numpy as np
import torchvision.transforms as T
from torchvision.transforms.functional import InterpolationMode
from PIL import Image
import time
import onnxruntime
from transformers import CLIPImageProcessor
if __name__ == '__main__':
img_sess_options = onnxruntime.SessionOptions()
img_run_options = onnxruntime.RunOptions()
img_run_options.log_severity_level = 2
img_onnx_model_path = "/media/star/8T/tmp/InternViT-6B-448px-V1-5/onnx/visual_encoder.onnx"
pixel_values = torch.tensor(np.load("/media/star/8T/tmp/internvn2_40b_image2_patch1.npy")).to(torch.float16)
print(f"pixel_values.shape={pixel_values.shape}")
img_session = onnxruntime.InferenceSession(img_onnx_model_path,
sess_options=img_sess_options,
providers=["CUDAExecutionProvider"])
onnx_image_features = img_session.run(["output"], {"input": pixel_values.cpu().numpy()})[
0]
onnx_image_features = torch.tensor(onnx_image_features).cuda()
print(f"onnx_image_features.shape={onnx_image_features.shape}")
print(f"onnx_image_features={onnx_image_features}")
The inference code for TRT engine is:
import tensorrt_llm
from tensorrt_llm import logger
from tensorrt_llm._utils import str_dtype_to_trt
from tensorrt_llm.runtime import Session, TensorInfo
import os
import torch
import tensorrt as trt
import numpy as np
import torchvision.transforms as T
from torchvision.transforms.functional import InterpolationMode
from PIL import Image
import time
from transformers import AutoModel,AutoTokenizer
import math
def trt_dtype_to_torch(dtype):
if dtype == trt.float16:
return torch.float16
elif dtype == trt.float32:
return torch.float32
elif dtype == trt.int32:
return torch.int32
elif dtype == trt.bfloat16:
return torch.bfloat16
else:
raise TypeError("%s is not supported" % dtype)
vision_precision="float16"
if vision_precision=="float16":
torch_dtype = torch.float16
else:
torch_dtype = torch.float
start_time=time.time()
image=torch.tensor(np.load("/data/eas/ndarray/internvn2_40b_image2_patch1.npy")).to(torch_dtype).cuda()
print(f"load image time is {time.time()-start_time} seconds")
# print(f"image pixels={image}")
print(f"origin image.shape={image.shape}")
image=torch.concat([image]*1, dim=0)
print(f"new image.shape={image.shape}")
iter_num=1
#=======================================================================================================================
attention_mask=None
stream = torch.cuda.Stream(torch.cuda.current_device())
torch.cuda.set_stream(stream)
vision_encoder_path="/data/eas/visual_engine/a100/InternViT-6B-448px-V1-5/visual_encoder.trtexec.best.maxBatchSize24.engine"
logger.info(f'Loading engine from {vision_encoder_path}')
with open(vision_encoder_path, 'rb') as f:
engine_buffer = f.read()
logger.info(f'Creating session from engine {vision_encoder_path}')
visual_encoder_session = Session.from_serialized_engine(
engine_buffer)
visual_features = {'input':image.to(tensorrt_llm._utils.str_dtype_to_torch(vision_precision))}
if attention_mask is not None:
visual_features['attention_mask'] = attention_mask
tensor_info = [TensorInfo('input', str_dtype_to_trt(vision_precision),image.shape)]
if attention_mask is not None:
tensor_info.append(TensorInfo('attention_mask', trt.DataType.INT32,attention_mask.shape))
visual_output_info = visual_encoder_session.infer_shapes(tensor_info)
visual_outputs = {
t.name: torch.empty(tuple(t.shape),
dtype=trt_dtype_to_torch(t.dtype),
device=image.device)
for t in visual_output_info
}
start_time=time.time()
for _ in range(iter_num):
ok = visual_encoder_session.run(visual_features, visual_outputs, stream.cuda_stream)
assert ok, "Runtime execution failed for vision encoder session"
stream.synchronize()
print(f"tensorrt,single image run time is {round((time.time()-start_time)/(iter_num),2)} seconds")
outputs_trt = visual_outputs['output']
outputs_trt=torch.squeeze(outputs_trt)
print(f"outputs_trt.shape={outputs_trt.shape}")
print(f"outputs_trt={outputs_trt}")
The inference results are as follows:
InternViT-6B-448px-V1-5
hf
outputs.last_hidden_state=tensor([[[ 1.0576, -4.4062, 1.1816, ..., 0.4963, 0.5752, 0.4436],
[ 3.6680, 4.8086, 4.7578, ..., -14.2969, 6.4336, -12.0312],
[ 3.9355, 4.4805, 4.4922, ..., -14.7031, 6.2812, -11.2266],
...,
[ -2.5684, -2.8164, 5.3242, ..., -7.0508, 0.2556, -6.5859],
[ -6.5156, -6.5859, 9.9531, ..., -4.0938, -4.5703, -14.6719],
[ -6.2383, -6.2930, 10.0391, ..., -3.8965, -4.2891, -15.1016]]],
device='cuda:0', dtype=torch.float16, grad_fn=<AddBackward0>)
outputs.last_hidden_state.shape=torch.Size([1, 1025, 3200])
onnx
onnx_image_features=tensor([[[ 1.0508, -4.3672, 1.1572, ..., 0.4902, 0.5601, 0.4417],
[ 3.6680, 4.8086, 4.7539, ..., -14.2969, 6.4180, -12.0391],
[ 3.9316, 4.4805, 4.4805, ..., -14.6953, 6.2656, -11.2188],
...,
[ -2.5840, -2.8320, 5.3555, ..., -7.0664, 0.2539, -6.6055],
[ -6.5195, -6.5898, 9.9375, ..., -4.0977, -4.5781, -14.6641],
[ -6.2461, -6.2891, 10.0234, ..., -3.9062, -4.2930, -15.0938]]],
device='cuda:0', dtype=torch.float16)
trt_exec
outputs_trt=tensor([[ 1.6309, -3.6855, 2.2578, ..., 0.0575, 1.1006, -0.1124],
[ 4.1562, 3.1484, 5.3594, ..., -10.8594, 6.0859, -10.5625],
[ 4.8984, 2.9824, 5.1719, ..., -11.0938, 6.1602, -9.5312],
...,
[ -0.2856, -3.4414, 5.4531, ..., -3.5000, 0.0735, -5.1602],
[ -3.1660, -5.7734, 8.8047, ..., -4.5742, -3.1387, -10.2969],
[ -3.0371, -5.5156, 8.8984, ..., -4.5469, -3.0234, -10.8906]],
device='cuda:0', dtype=torch.float16)
Environment
TensorRT Version:v100500
NVIDIA GPU:A100
NVIDIA Driver Version:535.54.03
CUDA Version:12.2
CUDNN Version:8920
Operating System: docker mirror: nvidia_cuda_12.4.0-devel-ubuntu22.04
Python Version (if applicable):3.10.12
Tensorflow Version (if applicable):
PyTorch Version (if applicable):2.2.2+cu121
Baremetal or Container (if so, version):docker
Relevant Files
Model link: https://huggingface.co/OpenGVLab/InternViT-6B-448px-V1-5
internvn2_40b_image2_patch1.npy: internvn2_40b_image2_patch1.zip
onnx file link: https://drive.google.com/file/d/1lnEmuQ4cNzf8YA7ddznqUnYsz-W5y5aJ/view?usp=sharing
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked InternViT-6B-448px-V1-5 model, the provided .npy input, and the ONNX file, then reproduce the three paths shown: Hugging Face, ONNX Runtime, and the trtexec-built engine. Compare the outputs and the TensorRT engine configuration around the trtexec entry point; done means identifying why the TensorRT result diverges or documenting the required reproducible fix.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, pytorch
- Domain
- machine-learning
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100