Linux平台CUDA+OpenCV3.4配置

 

前段时间,在TX2上装了OpenCV3.4,TX2更新源失败的问题,OpenCV内部很多函数都已经实现了GPU加速,但是我们手动写的函数,想要通过GPU加速就需要手动调用CUDA进行加速。下面介绍Linux平台的环境配置以及与OpenCV混合编译。

Linux平台CUDA+OpenCV3.4配置

1 环境安装

 

首先需要安装OpenCV及CUDA环境安装,有TX2平台下OpenCV和CUDA参考百度。注意TX2自带了OpenCV2.14,如果需要安装高版本的OpenCV话需要注意多版本管理的问题。安装完成后,可以编译OpenCV例程来判断OpenCV是否安转完成,CUDA安装可以在终端输入

nvcc

如果终端打印下面信息,表示安装完成

 

2 CUDA编译流程

 

CUDA的程序通过nvcc编译器编译成可执行文件,CUDA的可执行文件有两种,分别是在Host上执行的CPU相关代码,另一部分是在Device上执行的GPU代码,nvcc编译的指令与gcc/g++编译器差不多,基本指令如下

nvcc --gpu-architecture=compute_62 --gpu-code=compute_62 -I/usr/local/cuda/include/  -c kernels.cu -o kernels.o

其中:

--gpu-architecture和--gpu-code指定了GPU的计算能力,请根据自己GPU的运算能力修改,有关GPU运算能力可以在这里查找(NVIDIA官网挂了,将就着在维基百科里面看吧),--gpu-architecture指定ptx将来可以生成怎么样的版本,--gpu-code指定马上生成的代码版本,--gpu-architecture和--gpu-code可以有多个值,这样nvcc会将多个版本的代码一同放在fatbin文件中,

-I/usr/local/cuda/include/指定了CUDA包含头文件的目录,如果还有其他的头文件,要将这些头文件的路径包含进来(见3)

-c表示只对源文件进行编译,不进行链接,及将.cu文件编译生成.cu文件

-o指定要生成.o文件的文件名

还有其他的一些编译选项可以参考NVIDIA的nvcc编译手册,在CUDA的安装目录下可以找到

 

3 CUDA与OpenCV混合编译

 

CUDA与OpenCV的混合编译其实就是讲.cu文件与.c/.cpp文件混合编译,编译的方法比较多,NVIDIA官网有介绍利用cmake进行编译的方法,点这里,网上介绍的比较多的也是利用cmake进行编译,使用Makefile编译的教程比较少,这里介绍一下利用Makefile对CUDA与c++进行混合编译。

其实CUDA与c/c++一起编译原理很简单,CUDA C也只是一个拓展的c语言集,所以我采用的是利用nvcc编译器和g++分别对.cu文件和.cpp文件进行编译,生成.o文件,然后利用g++进行链接,实测方法可行。因为我CUDA的程序全部都在.cu文件中,然后在.cpp文件中通过extern对CUDA的函数申明,像下面这样:

/*main.cpp*/

extern int buildMaps(float *model, float *input, float *output, int height, int width);

int main()
{
    /*初始化代码*/
    ......    

    buildMaps((float *)model, (float *)input, output, width, width);

    /*other*/
    ......
}
/*kernel.cu*/

/*GPU内核函数*/
__global__ void kernel_compute(float *model, float *input, float *output)
{
    ......
}

int buildMaps(float *model, float *input, float *output, int height, int width)
{
     /*init*/
    ......

    kernel_compute <<<grid, block>>> (dev_m, dev_i, dev_o);

    /*other*/
    ......
}

所以这里的OpenCV代码像普通OpenCV代码一样写Makefile就行,写CUDA的代码的Makefile时注意,如果.cu文件中有OpenCV的相关代码的话,需要在nvcc编译的时候添加

-DOPENCV `pkg-config --cflags opencv-3.4`

用来指定OpenCV的包含头文件路径,没有错误的话,编译完成就可以使用g++链接就可以了。

这里贴一下我自己在用的一个Makefile模板,写的比较粗糙,不过平常的编译基本够了,中小型的工程的Makefile都可以用这个模板修改的到,模板有不完善的地方还请大家指正

#cpp源文件路径
SRCS = $(wildcard ./src/*.cpp)

#cu文件路径
CU_SRC = $(wildcard ./src/*.cu)

#.o文件
OBJS = $(patsubst %.cpp,%.o,$(SRCS))
CU_OBJ = $(patsubst %.cu,%.o,$(CU_SRC))

#g++和nvcc编译器
CXX = g++
NVCC = nvcc

#C/C++编译选项  --  OpenCV头文件路径
CFLAGS = `pkg-config --cflags opencv-3.4`

#C/C++编译选项  --  当前工程头文件路径及优化选项(-O3)
CFLAGS += -I./include/ -std=c++11 -O3 

#开启OpenMP
CFLAGS += -fopenmp

#CUDA C编译选项
NVFLAGS = --gpu-architecture=compute_62 --gpu-code=compute_62 
NVFLAGS += -DOPENCV `pkg-config --cflags opencv-3.4`

#C/C++链接器选项  -- OpenCV库及其路径
LDFLAGS = `pkg-config --libs opencv-3.4` -O3
LDFLAGS += -fopenmp

#C/C++链接器选项  -- CUDA8.0库及其路径
NVLDFLAGS = `pkg-config --libs cuda-8.0`

#最终目标
EXE = video

#OpenMP选项  --  指定绑定CPU
GOMP_CPU_AFFINITY="0 3 4 5"

#链接
$(EXE) : $(OBJS) $(CU_OBJ)
    @echo Linking ...
    @$(CXX) -o $@ $^ $(LDFLAGS) $(NVLDFLAGS)

#C/C++编译
%.o : %.cpp
    @echo Compiling $< ...
    @$(CXX) $(CFLAGS) -c $<
    @-mv *.o src/

#CUDA C编译
%.o : %.cu
    @echo NVCC Compiling $< ...
    @$(NVCC) $(NVFLAGS) -c $<
    @-mv *.o src/

.PHONY:clean

clean :
    -rm src/*.o
    -rm $(EXE)

 

posted @ 2018-01-22 23:12  Brccq  阅读(4823)  评论(0编辑  收藏  举报