{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#\n", "# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved.\n", "#\n", "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# http://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License.\n", "#" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Check the TensorRT version" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!python3 -c 'import tensorrt; print(\"TensorRT version: {}\".format(tensorrt.__version__))'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Prepare the input image and ONNX model file" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!python3 /workspace/TensorRT/quickstart/SemanticSegmentation/export.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Build TensorRT engine from the ONNX model" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!trtexec --onnx=fcn-resnet101.onnx --saveEngine=fcn-resnet101.engine --optShapes=input:1x3x1026x1282 --stronglyTyped" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Import required modules" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import os\n", "import ctypes\n", "from cuda.bindings import runtime as cudart\n", "import tensorrt as trt\n", "\n", "import matplotlib.pyplot as plt\n", "from PIL import Image\n", "\n", "TRT_LOGGER = trt.Logger()\n", "\n", "assert cudart.cudaSetDevice(0) == (cudart.cudaError_t.cudaSuccess,)\n", "\n", "# Filenames of TensorRT plan file and input/output images.\n", "engine_file = \"/workspace/fcn-resnet101.engine\"\n", "input_file = \"/workspace/input.ppm\"\n", "output_file = \"/workspace/output.ppm\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Utilities for input / output processing" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# For torchvision models, input images are loaded in to a range of [0, 1] and\n", "# normalized using mean = [0.485, 0.456, 0.406] and stddev = [0.229, 0.224, 0.225].\n", "def preprocess(image):\n", " # Mean normalization\n", " mean = np.array([0.485, 0.456, 0.406]).astype('float32')\n", " stddev = np.array([0.229, 0.224, 0.225]).astype('float32')\n", " data = (np.asarray(image).astype('float32') / float(255.0) - mean) / stddev\n", " # Switch from HWC to to CHW order\n", " return np.moveaxis(data, 2, 0)\n", "\n", "def postprocess(data):\n", " num_classes = 21\n", " # create a color palette, selecting a color for each class\n", " palette = np.array([2 ** 25 - 1, 2 ** 15 - 1, 2 ** 21 - 1])\n", " colors = np.array([palette*i%255 for i in range(num_classes)]).astype(\"uint8\")\n", " # plot the segmentation predictions for 21 classes in different colors\n", " img = Image.fromarray(data.astype('uint8'), mode='P')\n", " img.putpalette(colors)\n", " return img\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Load TensorRT engine" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Deserialize the TensorRT engine from specified plan file. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def load_engine(engine_file_path):\n", " assert os.path.exists(engine_file_path)\n", " print(\"Reading engine from file {}\".format(engine_file_path))\n", " with open(engine_file_path, \"rb\") as f, trt.Runtime(TRT_LOGGER) as runtime:\n", " return runtime.deserialize_cuda_engine(f.read())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Inference pipeline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Starting with a deserialized engine, TensorRT inference pipeline consists of the following steps:\n", "- Create an execution context and specify input shape (based on the image dimensions for inference).\n", "- Allocate CUDA device memory for input and output.\n", "- Allocate CUDA page-locked host memory to efficiently copy back the output.\n", "- Transfer the processed image data into input memory using asynchronous host-to-device CUDA copy.\n", "- Kickoff the TensorRT inference pipeline using the asynchronous execute API.\n", "- Transfer the segmentation output back into pagelocked host memory using device-to-host CUDA copy.\n", "- Synchronize the stream used for data transfers and inference execution to ensure all operations are completes.\n", "- Finally, write out the segmentation output to an image file for visualization." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def infer(engine, input_file, output_file):\n", " print(\"Reading input image from file {}\".format(input_file))\n", " with Image.open(input_file) as img:\n", " input_image = preprocess(img)\n", " image_width = img.width\n", " image_height = img.height\n", "\n", " with engine.create_execution_context() as context:\n", " input_buffers = {}\n", " input_memories = {}\n", "\n", " # Allocate host and device buffers\n", " tensor_names = [engine.get_tensor_name(i) for i in range(engine.num_io_tensors)]\n", " for tensor in tensor_names:\n", " size = trt.volume(context.get_tensor_shape(tensor))\n", " dtype = trt.nptype(engine.get_tensor_dtype(tensor))\n", "\n", " if engine.get_tensor_mode(tensor) == trt.TensorIOMode.INPUT:\n", " context.set_input_shape(tensor, (1, 3, image_height, image_width))\n", " input_buffers[tensor] = np.ascontiguousarray(input_image)\n", " err, input_memories[tensor] = cudart.cudaMalloc(input_image.nbytes)\n", " assert err == cudart.cudaError_t.cudaSuccess\n", " context.set_tensor_address(tensor, input_memories[tensor])\n", " else:\n", " err, output_buffer_ptr = cudart.cudaMallocHost(size * dtype().itemsize)\n", " assert err == cudart.cudaError_t.cudaSuccess\n", " pointer_type = ctypes.POINTER(np.ctypeslib.as_ctypes_type(dtype))\n", " output_buffer = np.ctypeslib.as_array(ctypes.cast(output_buffer_ptr, pointer_type), (size,))\n", "\n", " err, output_memory = cudart.cudaMalloc(output_buffer.nbytes)\n", " assert err == cudart.cudaError_t.cudaSuccess\n", " context.set_tensor_address(tensor, output_memory)\n", "\n", " err, stream = cudart.cudaStreamCreate()\n", " assert err == cudart.cudaError_t.cudaSuccess\n", "\n", " # Transfer input data to the GPU for all input tensors\n", " for tensor_name, input_buffer in input_buffers.items():\n", " input_memory = input_memories[tensor_name]\n", " err, = cudart.cudaMemcpyAsync(input_memory, input_buffer.ctypes.data, input_buffer.nbytes,\n", " cudart.cudaMemcpyKind.cudaMemcpyHostToDevice, stream)\n", " assert err == cudart.cudaError_t.cudaSuccess\n", "\n", " # Run inference\n", " context.execute_async_v3(stream)\n", "\n", " # Transfer prediction output from the GPU.\n", " err, = cudart.cudaMemcpyAsync(output_buffer.ctypes.data, output_memory, output_buffer.nbytes,\n", " cudart.cudaMemcpyKind.cudaMemcpyDeviceToHost, stream)\n", " assert err == cudart.cudaError_t.cudaSuccess\n", " # Synchronize the stream\n", " err, = cudart.cudaStreamSynchronize(stream)\n", " assert err == cudart.cudaError_t.cudaSuccess\n", "\n", " output_d64 = np.array(output_buffer, dtype=np.int64)\n", " np.savetxt('test.out', output_d64.astype(int), fmt='%i', delimiter=' ', newline=' ')\n", "\n", " with postprocess(np.reshape(output_buffer, (image_height, image_width))) as img:\n", " print(\"Writing output image to file {}\".format(output_file))\n", " img.convert('RGB').save(output_file, \"PPM\")\n", "\n", " # cleanup cuda resources for all input tensors\n", " for input_memory in input_memories.values():\n", " cudart.cudaFree(input_memory)\n", " cudart.cudaFree(output_memory)\n", " cudart.cudaFreeHost(output_buffer_ptr)\n", " cudart.cudaStreamDestroy(stream)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Plot input image" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.imshow(Image.open(input_file))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Run inference" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Running TensorRT inference for FCN-ResNet101\")\n", "with load_engine(engine_file) as engine:\n", " infer(engine, input_file, output_file)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Plot segmentation output" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.imshow(Image.open(output_file))" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.12" } }, "nbformat": 4, "nbformat_minor": 4 }