zoukankan      html  css  js  c++  java
  • 编译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 FilesNVIDIA GPU Computing ToolkitCUDAv7.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;
        }
  • 相关阅读:
    ORACLE SQL性能优化系列 (十一)
    ORACLE SQL性能优化系列 (七)
    ORACLE SQL性能优化系列 (十三)
    Oracle绑定变量
    ORACLE SQL性能优化系列 (九)
    C#中&与&&的区别
    简单代码生成器原理剖析
    C#线程系列讲座(1):BeginInvoke和EndInvoke方法
    ClearCanvas DICOM 开发系列 一
    C# winform 获取当前路径
  • 原文地址:https://www.cnblogs.com/xiaowangba/p/6313903.html
Copyright © 2011-2022 走看看