yolo infer docker 實現

cold_moon發表於2024-09-06
docker pull nvcr.io/nvidia/tensorrt:22.12-py3
docker run -it --privileged --network host --gpus all \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-e DISPLAY \
--device=/dev/bus/usb \
-v /etc/localtime:/etc/localtime:ro \
-v ~/workspace:/workspace \
--name yolo_infer  \
--workdir=/workspace \
nvcr.io/nvidia/tensorrt:22.12-py3 /bin/bash

這個 docker run 命令用於啟動一個容器,支援 GPU、USB 裝置、網路以及圖形介面的執行,具體解釋如下:

  1. -it:互動模式,-i 保持輸入流,-t 分配一個偽終端。用於在容器內執行互動式 shell。

  2. --privileged:賦予容器超級許可權,允許訪問主機上的所有裝置和資源。適用於需要與硬體、系統資源打交道的應用。

  3. --network host:使用主機網路模式,容器的網路配置與主機一致,這樣容器可以直接使用主機的網路介面。

  4. --gpus all:啟用對主機所有 GPU 的訪問,用於需要 GPU 加速的應用程式,如深度學習、計算加速等。

  5. -v /tmp/.X11-unix:/tmp/.X11-unix:將主機的 X11 Unix socket 掛載到容器中,允許容器中的應用透過主機的 X11 伺服器顯示圖形介面。通常與 DISPLAY 環境變數配合使用。

  6. -e DISPLAY:設定 DISPLAY 環境變數,指定容器的 GUI 應用程式輸出到主機的螢幕上。

  7. --device=/dev/bus/usb:掛載主機的 USB 匯流排裝置到容器中,允許容器與主機的 USB 裝置進行直接通訊,比如攝像頭、感測器等裝置。

  8. -v /etc/localtime:/etc/localtime:ro:將主機的本地時間和時區設定掛載到容器中,確保容器內的時間與主機保持一致。以只讀模式掛載,避免容器修改主機時間配置。

  9. -v ~/workspace:/workspace:將主機的 ~/workspace 目錄掛載到容器的 /workspace 目錄,允許容器訪問主機的工作空間,便於讀取或儲存資料。

  10. --name yolo_infer:為容器指定名稱 yolo_infer,方便之後管理和操作容器。

  11. nvcr.io/nvidia/tensorrt:22.12-py3:使用名為 nvcr.io/nvidia/tensorrt 的 Docker 映象,版本號為 22.12-py3

  12. /bin/bash:啟動容器後進入 Bash shell,提供互動式命令列環境。

這個命令整體用於執行一個帶有高許可權、支援 GPU 和 USB 裝置、並且能夠執行 GUI 應用的容器環境,適合執行像 YOLO 這樣需要硬體加速和外部裝置支援的應用。

git clone https://github.com/shouxieai/infer.git
cd infer/
修改 Makefile:
# 定義編譯器
cc        := g++
nvcc      := /usr/local/cuda/bin/nvcc
 
# 定義原始檔和目標檔案
cpp_srcs  := $(shell find src -name "*.cpp")
cpp_objs  := $(cpp_srcs:.cpp=.cpp.o)
cpp_objs  := $(cpp_objs:src/%=objs/%)
cpp_mk := $(cpp_objs:.cpp.o=.cpp.mk)
 
cu_srcs	  := $(shell find src -name "*.cu")
cu_objs   := $(cu_srcs:.cu=.cu.o)
cu_objs	  := $(cu_objs:src/%=objs/%)
cu_mk	  := $(cu_objs:.cu.o=.cu.mk)
 
include_paths := src \
	/usr/include/opencv4 \
	/usr/local/cuda/include \
	/usr/include/x86_64-linux-gnu/TensorRT


# 庫檔案路徑
library_paths := /usr/local/cuda/lib64 \
    /usr/lib/x86_64-linux-gnu \
    /usr/local/cuda/lib64/stubs \
    /usr/lib/x86_64-linux-gnu/TensorRT \
    /usr/local/cuda/lib64/stubs \
    /usr/local/cuda/lib64
 
 
link_librarys := opencv_core opencv_imgproc opencv_videoio opencv_imgcodecs \
				 nvinfer nvinfer_plugin nvonnxparser \
				 cuda cublas cudart cudnn \
				 stdc++ dl
 
# 定義匯出和執行時路徑
empty		  :=
export_path   := $(subst $(empty) $(empty),:,$(library_paths))
 
run_paths     := $(foreach item,$(library_paths),-Wl,-rpath=$(item))
 
# 定義編譯選項
include_paths := $(foreach item,$(include_paths),-I$(item))
library_paths := $(foreach item,$(library_paths),-L$(item))
link_librarys := $(foreach item,$(link_librarys),-l$(item))
 
cpp_compile_flags := -std=c++11 -fPIC -w -g -pthread -fopenmp -O0
cu_compile_flags  := -std=c++11 -g -w -O0 -Xcompiler "$(cpp_compile_flags)"
link_flags        := -pthread -fopenmp -Wl,-rpath='$$ORIGIN'
 
cpp_compile_flags += $(include_paths)
cu_compile_flags  += $(include_paths)
link_flags        += $(library_paths) $(link_librarys) $(run_paths)
 
# 新增標頭檔案依賴
ifneq ($(MAKECMDGOALS), clean)
-include $(cpp_mk) $(cu_mk)
endif
 
# 編譯CUDA和C++程式
pro	   := workspace/pro
expath := library_path.txt
 
library_path.txt : 
	@echo LD_LIBRARY_PATH=$(export_path):"$$"LD_LIBRARY_PATH > $@
 
workspace/pro : $(cpp_objs) $(cu_objs)
	@echo Link $@
	@mkdir -p $(dir $@)
	@$(cc) $^ -o $@ $(link_flags)
 
objs/%.cpp.o : src/%.cpp
	@echo Compile CXX $<
	@mkdir -p $(dir $@)
	@$(cc) -c $< -o $@ $(cpp_compile_flags)
 
objs/%.cu.o : src/%.cu
	@echo Compile CUDA $<
	@mkdir -p $(dir $@)
	@$(nvcc) -c $< -o $@ $(cu_compile_flags)
 
objs/%.cpp.mk : src/%.cpp
	@echo Compile depends CXX $<
	@mkdir -p $(dir $@)
	@$(cc) -M $< -MF $@ -MT $(@:.cpp.mk=.cpp.o) $(cpp_compile_flags)
 
objs/%.cu.mk : src/%.cu
	@echo Compile depends CUDA $<
	@mkdir -p $(dir $@)
	@$(nvcc) -M $< -MF $@ -MT $(@:.cu.mk=.cu.o) $(cu_compile_flags)
 
run : workspace/pro
	@cd workspace && ./pro
 
# 其它
debug :
	@echo $(include_paths)
	@echo $(library_paths)
	@echo $(link_librarys)
 
clean : 
	@rm -rf library_path.txt
	@rm -rf objs workspace/pro
	@rm -rf workspace/Result.jpg
 
.PHONY : debug clean run
 
export LD_LIBRARY_PATH:=$(export_path):$(LD_LIBRARY_PATH)
wget -O workspace/yolov5s.onnx  https://github.com/ultralytics/yolov5/releases/download/v7.0/yolov5s.onnx --no-check-certificate
trtexec --onnx=workspace/yolov5s.onnx --saveEngine=workspace/yolov5s.engine
make run

報錯:fatal error: opencv2/opencv.hpp: No such file or directory

apt update
apt install libopencv-dev
ls /usr/include/opencv4
make run
輸出結果
Compile depends CXX src/main.cpp
Compile CXX src/main.cpp
Compile CUDA src/yolo.cu
Compile CUDA src/infer.cu
Link workspace/pro
[infer.cu:393]: Infer 0x7f2b88000d70 [StaticShape]
[infer.cu:405]: Inputs: 1
[infer.cu:409]: 	0.images : shape {1x3x640x640}
[infer.cu:412]: Outputs: 1
[infer.cu:416]: 	0.output0 : shape {1x25200x85}
[yolo.cu:574]: When using static shape model, number of images[16] must be less than or equal to the maximum batch[1].
[BATCH16]: 0.05018 ms
[yolo.cu:574]: When using static shape model, number of images[16] must be less than or equal to the maximum batch[1].
[BATCH16]: 0.12086 ms
[yolo.cu:574]: When using static shape model, number of images[16] must be less than or equal to the maximum batch[1].
[BATCH16]: 0.10445 ms
[yolo.cu:574]: When using static shape model, number of images[16] must be less than or equal to the maximum batch[1].
[BATCH16]: 0.10317 ms
[yolo.cu:574]: When using static shape model, number of images[16] must be less than or equal to the maximum batch[1].
[BATCH16]: 0.02646 ms
[BATCH1]: 190.41962 ms
[BATCH1]: 4.47782 ms
[BATCH1]: 4.47869 ms
[BATCH1]: 4.36294 ms
[BATCH1]: 4.35104 ms
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(MyProject)

# 設定 C++ 標準
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# 指定 CUDA 的位置和版本
find_package(CUDA REQUIRED)
find_package(OpenCV REQUIRED)
# find_package(TensorRT REQUIRED)

# 原始檔
file(GLOB_RECURSE CPP_SRCS src/*.cpp)
file(GLOB_RECURSE CU_SRCS src/*.cu)

# 包含路徑
include_directories(
    src
    ${OpenCV_INCLUDE_DIRS}
    ${CUDA_INCLUDE_DIRS}
)

# 連結庫路徑
link_directories(
    /usr/local/cuda/lib64
    /usr/lib/x86_64-linux-gnu
)

# 庫檔案
set(LINK_LIBS
    ${OpenCV_LIBS}
    nvinfer nvinfer_plugin nvonnxparser
    cuda cublas cudart cudnn
    stdc++ dl
)

# 新增編譯選項
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -std=c++11 -O0 -g")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -pthread -fopenmp -O0")

# 編譯目標
cuda_add_executable(${PROJECT_NAME} ${CPP_SRCS} ${CU_SRCS})

# 連結庫
target_link_libraries(${PROJECT_NAME} ${LINK_LIBS})

# 設定 RPATH
set_target_properties(${PROJECT_NAME} PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)

# 執行命令
add_custom_target(run
    COMMAND ${PROJECT_NAME}
    DEPENDS ${PROJECT_NAME}
)

chmod 777 ./workspace/build.sh
./workspace/build.sh

cd workspace
cmake ..
make run

相關文章