YOLOv3 on Jetson AGX Xavier 성능 평가


18년 4월에 공개된 YOLOv3를 최신 embedded board인 Jetson agx xavier에서 구동시켜서 FPS를 측정해 본다.
그리고 tegra코어가 아닌 Geforece 1080과의 성능 비교도 수행해 본다.

YOLOv3 관련 정보

SSD가 주류가되고 약간 비주류가된 deep learning기반 object detection 알고리즘이다. 하지만 다른 프레임워크를 쓰지않고 독자적이며 의존성이 거의없는 깔끔한 코드이므로 향후 분석하기 용이하므로 이것을 사용 한다.

pretrained weights들은 아래의 표와 같고 각각은 Link에서 다운로드 할 수 있다.
스크린샷 2019-01-10 오후 3.03.00

NVIDIA Jetson Xavier에서 YOLOv3 다운 및 컴파일

소스 및 모델 다운

우선, 아래주소에서 소스코드와 모델 웨이트를 다운로드한다.

git clone https://github.com/pjreddie/darknet # 코드 다운로드
cd darknet
wget https://pjreddie.com/media/files/yolov3.weights # weights 다운로드

Makefile 수정

그 다음 Makefile을 수정한다. 이 때 CUDA Compute Capability를 맞춰서 수행 해야한다.

NVIDIA GPU: CUDA Compute Capability의 이해
CUDA를 활성화해서 컴파일 할 경우 Compute Capability의 이해를 필요로 한다.
허용하지 않는 아키텍쳐라면 아래와 같은 에러를 발생 시킨다.

  • nvcc fatal: Unsupported gpu architecture 'compute_XX'
    해결방법은 nvcc 컴파일을 수행 할 때 FLAG를 넣으면 된다.
  • -gencode arch=compute_XX, code=[sm_XX, compute_XX]이다.

원하는 장치에 맞춰서 적한한 코드를 NVIDIA CUDA-GPUs찾아서 넣으면 된다. GeForece-1080의 경우 6.1이므로-gencode arch=compute_61, code=[sm_61, compute_61]으로
삽입해서 넣으면 된다.
사용할 보드는 tegra 게열인데 Jetson Xavier는 아직 검색이 안 된다.
포럼에서 찾아본 결과 코드는 -gencode arch=compute_72,code=sm_72이다.

추가로, 어떤 머신에서 정확히 돌지 모른다면 여러개를 지원하도록 설정하여 컴파일 할 수도 있다.
아래와 같은 형태가 YOLOv3의 makefile의 구조이다. 사용할 Jetson Xavier용은 없으므로 추가해 주자.

ARCH= -gencode arch=compute_30,code=[sm_30,compute_30] \
      -gencode arch=compute_35,code=[sm_35,compute_35] \
      -gencode arch=compute_50,code=[sm_50,compute_50] \
      -gencode arch=compute_52,code=[sm_52,compute_52] \
      -gencode arch=compute_61,code=[sm_61,compute_61] \
      -gencode arch=compute_72,code=[sm_72,compute_72]

상단의 OPENCV=1 GPU=1 CUDNN=1 이 세개 모두 활성화 한다.
속도를 위해선 gpu cudnn을 활성화하고 real-time 데모를 위해서 opencv도 활성화한다.

컴파일

동작 속도를 빠르게 설정

sudo nvpmodel -m 0
jetson_clocks.sh

make -j4 명령어 수행

nvidia@jetson-0423718017159:~/Computer_Vision_Project/yolov3$ make -j4
mkdir -p obj
mkdir -p backup
mkdir -p results
gcc -Iinclude/ -Isrc/ -DOPENCV `pkg-config --cflags opencv`  -DGPU -I/usr/local/cuda/include/ -DCUDNN  -Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC -Ofast -DOPENCV -DGPU -DCUDNN -c ./src/gemm.c -o obj/gemm.o
gcc -Iinclude/ -Isrc/ -DOPENCV `pkg-config --cflags opencv`  -DGPU -I/usr/local/cuda/include/ -DCUDNN  -Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC -Ofast -DOPENCV -DGPU -DCUDNN -c ./src/utils.c -o obj/utils.o
gcc -Iinclude/ -Isrc/ -DOPENCV `pkg-config --cflags opencv`  -DGPU -I/usr/local/cuda/include/ -DCUDNN  -Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC -Ofast -DOPENCV -DGPU -DCUDNN -c ./src/cuda.c -o obj/cuda.o
gcc -Iinclude/ -Isrc/ -DOPENCV `pkg-config --cflags opencv`  -DGPU -I/usr/local/cuda/include/ -DCUDNN  -Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC -Ofast -DOPENCV -DGPU -DCUDNN -c ./src/deconvolutional_layer.c -o obj/deconvolutional_layer.o
./src/gemm.c: In function ‘time_gpu’:
./src/gemm.c:232:9: warning: ‘cudaThreadSynchronize’ is deprecated [-Wdeprecated-declarations]
         cudaThreadSynchronize();
         ^~~~~~~~~~~~~~~~~~~~~
In file included from /usr/local/cuda/include/cuda_runtime.h:96:0,
                 from include/darknet.h:11,
                 from ./src/utils.h:5,
                 from ./src/gemm.c:2:
/usr/local/cuda/include/cuda_runtime_api.h:947:57: note: declared here
 extern __CUDA_DEPRECATED __host__ cudaError_t CUDARTAPI cudaThreadSynchronize(void);
                                                         ^~~~~~~~~~~~~~~~~~~~~
gcc -Iinclude/ -Isrc/ -DOPENCV `pkg-config --cflags opencv`  -DGPU -I/usr/local/cuda/include/ -DCUDNN  -Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC -Ofast -DOPENCV -DGPU -DCUDNN -c ./src/convolutional_layer.c -o obj/convolutional_layer.o
...
...
...
bj/col2im_kernels.o obj/blas_kernels.o obj/crop_layer_kernels.o obj/dropout_layer_kernels.o obj/maxpool_layer_kernels.o obj/avgpool_layer_kernels.o
gcc -Iinclude/ -Isrc/ -DOPENCV `pkg-config --cflags opencv`  -DGPU -I/usr/local/cuda/include/ -DCUDNN  -Wall -Wno-unused-result -Wno-unknown-pragmas -Wfatal-errors -fPIC -Ofast -DOPENCV -DGPU -DCUDNN obj/captcha.o obj/lsd.o obj/super.o obj/art.o obj/tag.o obj/cifar.o obj/go.o obj/rnn.o obj/segmenter.o obj/regressor.o obj/classifier.o obj/coco.o obj/yolo.o obj/detector.o obj/nightmare.o obj/instance-segmenter.o obj/darknet.o libdarknet.a -o darknet -lm -pthread  `pkg-config --libs opencv` -lstdc++ -L/usr/local/cuda/lib64 -lcuda -lcudart -lcublas -lcurand -lcudnn -lstdc++  libdarknet.a

빌드가 완료되면 data 디렉터리 안에 몇개의 샘플 이미지들이 존재한다.
이것들을 가지고 테스트 할 수도 있고 비디오 영상을 다운받아서 할 수도 있다.

실행 및 성능 테스트

이미지 테스팅

아래는 하나의 이미지에 대해서 xaiver geforece에서 각각 수행해본 결과이다.

  • Xavier: 0.164729
  • Geforce-1080: 0.051647

그냥 darknet 자체를 날것으로 돌려서 성능차이는 3배정도 발생한다.
소비전력이 30W 120W수준의 차이이므로 성능차이는 적다고 할 수도 있겠다.

xavier

`./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg`
Loading weights from yolov3.weights...Done!
data/dog.jpg: Predicted in  `0.164729` seconds.

Geforce-1080

Loading weights from yolov3.weights...Done!
data/dog.jpg: Predicted in 0.051647 seconds.

영상 테스팅

detector명령어를 수행할 경우 영상과 Camera로 실시간 테스팅도 할 수 있다.

  • ./darknet detector demo cfg/coco.data cfg/yolov3.cfg yolov3.weights <video file>

동영상으로 아래와 같이 YOLOv3를 xavier에서 수행할 경우 대략 5~6 FPS가 측정 된다.
video demo

라이브 데모는 Youtube에서 볼수 있다.

참고자료

[1] 공식 wiki
[2] JK Jung's blog, YOLOv3 on Jetson TX2
[3] [중국 사이트] (http://takesan.hatenablog.com/entry/2018/10/07/003252)


+ Recent posts