编译GDAL支持OpenCL使用GPU加速

前言

GDAL库中提供的gdalwarp支持各种高性能的图像重采样算法,图像重采样算法广泛应用于图像校正,重投影,裁切,镶嵌等算法中,而且对于这些算法来说,计算坐标变换的运算量是相当少的,绝大部分运算量都在图像的重采样算法中,尤其是三次卷积采样以及更高级的重采样算法来说,运算量会成倍的增加,所以提升这些算法的处理效率优先是提高重采样的效率。由于GPU的多核心使得目前对于GPU的并行处理非常热,同时也能大幅度的提升处理速度。基于上述原因,GDALWARP也提供了基于OPENCL的GPU加速,之前在GDAL的邮件列表中有人测试发现使用OpenCL加速后,在Telsa的显卡上速度可以达到CPU的20~60倍。

GDAL库一般编译的时候不会打开,所以默认的GDAL是不支持GPU并行处理的,本文就是指导大家在Windows平台上使用Visual Studio系列编译GDAL时,怎么使之支持OpenCL并行处理。

所需软件

-Visual Studio 系列(VS2003以上版本)
-OpenCL库(AMD或者NVIDIA均可)
-GDAL源码

修改nmake.opt文件

nmake.opt文件中一共要修改四处地方,其中两处是添加,两处是修改。

第一处(增加)

首先在nmake.opt文件参考其他的引用库,添加OpenCL的库目录。首先在namke.opt找到下面这行:

########### END OF STUFF THAT NORMALLY NEEDS TO BE UPDATED ##################

在上面这行代码的前面添加如下代码(使用的是NVIDIA的CUDA安装包下面的OpenCL库):

#include opencl lib
INCLUDE_OPENCL = YES

# Uncomment for OPENCL_AMD support
!IFDEF INCLUDE_OPENCL
OPENCL_DIR="C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.0"
OPENCL_CFLAGS = -I$(OPENCL_DIR)/include -DHAVE_OPENCL
OPENCL_LIB    = $(OPENCL_DIR)/lib/Win32/OpenCL.lib
!ELSE
OPENCL_DIR=
OPENCL_CFLAGS = -I
OPENCL_LIB     = 
!ENDIF

第二处(增加)

然后在上面那行代码(END OF STUFF THAT NORMALLY NEEDS TO BE UPDATED)的下面添加下面的代码:

# liml
!IFDEF INCLUDE_OPENCL
OPENCL_FLAG = -DHAVE_OPENCL
!ENDIF

第三处(修改)

接下来找到代码CFLAGS = 这句代码,在这句代码的后面加上$(OPENCL_FLAG)

地四处(修改)

找到代码EXTERNAL_LIBS =,在最后面加上$(OPENCL_LIB)

修改alg目录下的makefile.vc文件

makefile.vc文件中共需要修改两处位置,一处增加一处修改。

第一处(增加)

在文件中OBJ = 的前面添加下面的代码,用来设置使用OpenCL的宏定义。

!IFDEF INCLUDE_OPENCL
EXTRAFLAGS = $(EXTRAFLAGS) $(OPENCL_CFLAGS) -DHAVE_OPENCL
!ENDIF

第二处(修改)

在文件中OBJ = 的后面添加OpenCL的算法文件gdalwarpkernel_opencl.obj。注意添加的时候与其他的obj文件中间用空格隔开。

编译

修改完上述文件之后,使用VS或者命令行编译,正常的话应该就直接编译通过了。如果编译不过提示.h文件无法打开啥的,请检查opencl的库的路径设置的是否有问题,如果opencl的路径中有空格的话,那么在nmake.opt文件中,路径用双引号括起来,如果最后提示连接错误,或者lib文件找不到,同样先检查opencl的库路径设置的是否正确,如果路径中有空格,同样用双引号括起来。

注意
如果你还是编译不过去,根据提示内容,修改gdalwarpkernel_opencl.h和文件gdalwarpkernel_opencl.c文件。我就遇到了这个问题,修改的是h文件,修改前后的代码如下(上方的是原来的代码,下方是修改后的代码):

#if defined(DEBUG_OPENCL) && DEBUG_OPENCL == 1
#define CL_USE_DEPRECATED_OPENCL_1_0_APIS
#endif
#if defined(DEBUG_OPENCL) && DEBUG_OPENCL == 1
#define CL_USE_DEPRECATED_OPENCL_1_0_APIS
#else
#define CL_USE_DEPRECATED_OPENCL_1_1_APIS
#endif

至此,编译如果没有问题的话,那么就可以使用depends之类的查看dll的依赖关系的软件来查看gdal的动态库,如果gdal的动态库依赖opencl.dll的话,那么应该就可以支持了,可以使用gdal自带的gdalwarp.exe进行测试是否支持opencl。
注意:GDAL库中的重采样算法支持opencl库的有双线性插值和三次立方卷积,最邻近采样是不支持OpenCL加速的,所以测试的时候请指定重采样算法进行测试。

两个问题

使用GDAL的GPU测试的时候发现下面两个问题:
1、使用OPENCL进行重采样时,只能使用第一个设备进行处理(比如我的笔记本可以获取到两个GPU设备,第一个是Intel的集成显卡,第二个才是Nvidia的独立显卡)
2、使用-wm参数设置大于显卡显存时,处理失败

第一个问题,我大致修改了下,参考下面的代码,第二个暂时没有。
对于第一个问题的修改,主要就是将默认使用的第一个设置,换成了使用最后一个设备,等有空了可以设置由用户指定使用那个设备进行处理。
修改前的代码:

    // Find the GPU CL device, this is what we really want
    // If there is no GPU device is CL capable, fall back to CPU
    err = clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_GPU, 1, &device, NULL);
    if (err != CL_SUCCESS)
    {
        // Find the CPU CL device, as a fallback
        err = clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_CPU, 1, &device, NULL);
        if( err != CL_SUCCESS || device == 0 )
            return NULL;
    }

修改后的代码

    // Find the GPU CL device, this is what we really want
    // If there is no GPU device is CL capable, fall back to CPU
    err = clGetDeviceIDs(platforms[num_platforms-1], CL_DEVICE_TYPE_GPU, 1, &device, NULL);
    if (err != CL_SUCCESS)
    {
        // Find the CPU CL device, as a fallback
        err = clGetDeviceIDs(platforms[num_platforms-1], CL_DEVICE_TYPE_CPU, 1, &device, NULL);
        if( err != CL_SUCCESS || device == 0 )
            return NULL;
    }

你可能感兴趣的:(高性能,OpenCL,GPU,GDAL,并行处理)