대규모 병렬연산이 필요한 경우 당연히 CPU보다 GPU를 사용하는 것이 성능상 유리하다. 그런데 OpenCV의 기본 배포판에는 CUDA를 이용한 버전이 포함되어 있지 않기 때문에, —이것은 실제 배포 과정을 따라가 보면 이해할 수 있는데, Computer의 GPU에 따라 버전이 달라지기 때문— CUDA가 포함된 extra 소스를 따로 받아서 Build를 해야 한다.
준비물
OpenCV CUDA를 만들기 위해서는 아래의 항목들이 필요하다. 설치 내용은 생략. CUDA와 cuDNN은 자신의 컴퓨터 그래픽카드 버전에 맞는 것을 받아야 한다.
•
OpenCV 배포판 소스 (opencv)
•
OpenCV CUDA가 포함된 Extra 소스 (opencv_contrib)
•
CMake-GUI 버전
•
NVIDIA CUDA + cuDNN
•
Visual Studio
CMake로 빌드하기
기본 설정
우선 설치한 CMake gui 프로그램을 실행시킨 후에 다음과 같이 입력한다.
•
‘where is the source code’ 부분에 opencv 배포판 소스 경로를 설정
◦
CMake가 이해할 수 있는 ‘CMakeLists.txt’이 있는 경로까지 잡아주면 된다.
•
‘where is build the binaries’ 부분에 빌드 된 소스 파일을 복사할 경로를 설정
그 후에 하단의 Configure 버튼을 선택한 후 다음과 같이 입력한다.
•
Specifiy the generator for this project 부분에 자신의 컴퓨터에 설치된 Visual Studio 버전을 선택
•
Optional platform for generator 부분에 x64 선택
•
그 외의 나머지 항목은 그대로 두고 finish
설정을 마치면 CMake가 알아서 설정을 읽어서 처리하고 아래와 같은 화면이 뜬다. —이 과정에서 CMake는 필요하면 인터넷에서 필요한 파일을 다운도 받기 때문에 인터넷에 연결되어 있어야 함
만일 설정 중에 에러가 났다면 빨간색으로 표시가 되면 검색해서 해결해야 한다. —python 관련 에러는 무시해도 무방
Extra 모듈 추가
에러 없이 마쳤다면, Search 항목에 extra를 입력하고, 나오는 항목의 value에 opencv_contrib 소스가 있는 경로의 ‘modules’까지의 경로를 입력한다.
CPU 설정
Search 항목에 CPU_BASELINE을 입력하고 value에 자신의 CPU에서 지원하는 CPU 명령어 셋을 선택한다.
CPU 명령어 셋은 자신이 사용하고 있는 컴퓨터 환경에 따라 다르기 때문에, 자신의 컴퓨터 CPU의 모델명을 확인해서 입력해줘야 한다. 인텔 CPU를 사용한다면 아래 주소에서 확인 가능하다.
필자는 AMD CPU를 사용하고 있었기 때문에 CPU 모델을 이용해서 사용하고 있는 SSE 버전을 찾아서 입력 했음 —AMD는 AVX 명령어 셋을 지원하지 않는다고 한다.
당연하겠지만, 만일 지금 만들고 있는 OpenCV Build 파일을 여러 대의 PC에서 사용한다고 가정할 때, 가장 성능이 안 좋은 PC를 기준으로 위 설정을 맞춰줘야 한다.
CUDA 설정
CUDA 관련 설정을 위해 우선 Search 항목에 WITH_CUDA를 입력하고 value에 체크를 한 뒤, Configure를 다시 수행한다. 그래야 처음에는 보이지 않는 CUDA 관련 설정을 할 수 있음.
GPU 설정
Search 항목에 CUDA_ARCH_BIN을 입력하고 value에 자신의 그래픽카드가 지원하는 버전을 입력한다.
GPU가 지원하는 버전은 컴퓨터 환경에 따라 다르기 떄문에, 자신의 그래픽카드의 모델명을 확인해서 입력해줘야 한다. 아래 사이트에서 확인 가능
이 Build를 여러 대의 PC에서 사용한다고 가정할 경우, 해당 그래픽카드의 버전을 모두 적으면 된다. 다만 여기에 많은 값이 입력될 수록 Build 시간이 길어지기 때문에 최소한으로 적는 것이 좋다.
기타 설정
앞선 설정과 같은 식으로 아래의 항목들을 찾아 다음과 같이 값을 설정한다. —설정에 대한 내용은 참조링크의 ‘OpenCV + CUDA 직접 빌드하기’ 참조.
•
BUILD_SHARED_LIBS = ON (static으로 빌드할 것이면 OFF)
•
BUILD_WITH_STATIC_CRT = OFF
•
BUILD_opencv_world = ON
•
OPENCV_ENABLE_NONFREE = ON
•
CPU_DISPATCH = (공백으로 둠)
•
OPENCV_DNN_CUDA = ON
•
WITH_CUDNN = ON
•
WITH_CUBLAS = ON
•
WITH_CUFFT = ON
•
CUDA_FAST_MATH = ON
솔루션 생성 및 빌드
설정을 마쳤으면 Generate 버튼을 클릭해서 소스 파일을 생성한다. 만들어진 소스 파일은 앞서 설정한 경로에 있으며 생성된 파일 중에 OpenCV.sln을 선택하면 프로젝트를 열 수 있다. —Open Project 버튼을 클릭하면 솔루션을 바로 실행할 수 있다.
솔루션을 실행하면 아래와 같은 구성을 가지고 있는데, 이 중에 CMakeTargets 폴더를 열어보면 ALL_BUILD 프로젝트가 보이고 이것이 기본 프로젝트로 설정되어 있음을 알 수 있다.
이 상태에서 Visual Studio에서 솔루션 빌드를 실행하면 빌드 파일이 만들어진다. 이때 시간이 엄청 오래 걸리므로 참고. 몇 시간이 걸릴 수 있다. Debug와 Release 모드로 각각 빌드를 수행한다.
빌드가 끝나면 ALL_BUILD 아래의 INSTALL 프로젝트만 선택해서 빌드를 수행한다. 그러면 아래와 같이 솔루션 폴더 내에 install 이라는 폴더가 생성된다.
install 폴더를 열어보면 OpenCV 배포판과 같은 폴더 구조를 갖고 있음을 알 수 있다.
이렇게 만들어진 파일이 바로 CUDA를 사용할 수 있는 OpenCV 라이브러리가 된다. OpenCV를 설치하는 것과 같은 방식으로 해당 라이브러리를 컴퓨터에 세팅한다. (아래 링크 참조)
설치 테스트
Window 환경 변수 세팅까지 마무리 됐다면 Visual Studio에서 OpenCV 세팅을 한 후 아래의 코드를 실행해서 제대로 설치 되었는지 확인한다. —참고로 공식 홈에는 namespace가 cuda가 아닌 gpu를 사용하는 예전 버전의 코드가 있어서 사용 불가.
#include <iostream>
#include "opencv2/opencv.hpp"
#include "opencv2/core/cuda.hpp"
#include "opencv2/cudaarithm.hpp"
int main (int argc, char* argv[])
{
try
{
cv::Mat src_host = cv::imread("file.png", cv::IMREAD_GRAYSCALE);
cv::cuda::GpuMat dst, src;
src.upload(src_host);
cv::cuda::threshold(src, dst, 128.0, 255.0, cv::THRESH_BINARY);
cv::Mat result_host;
dst.download(result_host);
cv::imshow("Result", result_host);
cv::waitKey();
}
catch(const cv::Exception& ex)
{
std::cout << "Error: " << ex.what() << std::endl;
}
return 0;
}
C++
복사
코드를 보면 알 수 있지만, 모든 CUDA를 사용하는 것들이 그러한 것처럼 GPU로 input을 보내고, GPU에서 연산을 수행한 후, 그 결과를 다시 CPU로 받아오는 과정이 포함되어 있다. —upload, download