gdal、geos的 windows编译 openCL加速

48 篇文章 2 订阅
9 篇文章 0 订阅

如果想gdal支持*.jp2影像,该文章也有继续篇:
编译支持JPEG2000压缩格式的GDAL(ECW库、OpenJPEG)

前言

由于最近在使用gdal的纠正功能,发现自带方法特别慢,经过研究发现以前的编译没有使用OpenGL的GPU加速功能,不得己重新编译一次完整的gdal库,特此记录。

此文编译的版本如下:
gdal版本: gdal2.2.0
geos版本:geos3.5.2

gdal官方下载地址:http://download.osgeo.org/gdal/
geos官方下载地址:http://download.osgeo.org/geos/

注意:gdal2.2.0使用OpenCL编译后会有GPU内存泄漏的bug,严重的时候会导致输出的影像图像部分损坏,本文后面也有测试。为了少走弯路可以直接从官网上下载gdal2.4.4版本进行本文方法的编译,经过测试GPU内存泄漏问题消失。

我这里也提供我编译好的两个版本供大家下载使用。
下载地址:
gdal220+geos352+opencl编译库
gdal244+geos352+opencl编译库

参考连接:
编译GDAL支持OpenCL使用GPU加速
windows编译GDAL+GEO+PROJ4(傻瓜教程)

上面两篇博文各有所长,但都不完善。我主要想得到的是gdal+geos+OpenCL功能,proj库我一直是单独使用的,在按照帖子进行编译过程中也遇到几个问题,与帖子不符,但后面都尝试解决了。现特此记录:
编译顺序:
1、先编译geos库,按照第二篇文章的部分进行:
2、再进行gdal库编译,编译前需要设置geos库、opengl库设置相关参数(重点)

一、编译GEOS库(使用nmake编译)

1、解压源码,如E:\geos3.5.2\geos-3.5.2路径下

2、修改nmake.opt文件,若编译64位库,需打开geos-3.7.1文件夹中的nmake.opt文件,将WIN64 = NO改为WIN64 = YES;32位无需修改。若编译Debug库,则将nmake.opt中的BUILD_DEBUG = NO改为BUILD_DEBUG = YES;Release无需修改。

3、打开VS的工具命令提示,若编32位则打开VS2013 x86 本机工具命令提示,若编64位则打开VS2013 x64 本机工具命令提示。并进入geos路径下,如cd E:\geos3.5.2\geos-3.5.2
注意:如果这里使用VS2017可能出现错误:.\nmake.opt(157) : fatal error U1050: *** Aborting make jobStop.
这时候需要修改nmake.opt文件设置,详见:
Geos库在Windows上的编译

4、依次在命令行输入autogen.bat和nmake /f makefile.vc进行编译

autogen.bat
nmake /f makefile.vc

结果如下图:
在这里插入图片描述

5、编译成功后,会在E:\geos3.5.2\geos-3.5.2\src目录下生成geos.lib, geos_i.lib, geos_c_i.lib, geos.dll, geos_c.dll等五个文件。该生成的文件可以接着用来生成GDAL库
在这里我是设置了BUILD_DEBUG = YES和BUILD_DEBUG = NO两种模式都分别进行了设置,所以输出文件多一些,如下图:
在这里插入图片描述

二、设置Geos库

(1)下载gdal库,解压。我使用的是E:\gdal220\gdal-2.2.0版本

(2) 修改E:\gdal220\gdal-2.2.0\nmake.opt,修改GDAL_HOME路径,如GDAL_HOME = “E:\gdal220\GDAL220_Out”;
(3)修改geo库依赖,首先将GEOS库前的注释去掉,分别设置GEOS_DIR、GEOS_CFLAGS和GEOS_LIB,其中GEOS_CFLAGS需要改为

-I$(GEOS_DIR)/capi -I$(GEOS_DIR)/include -DHAVE_GEOS

特别说明,设置的GEOS_DIR路径中不能有空格,设置完成后如下图所示:

在这里插入图片描述
在这里插入图片描述
这里需要注意,根据自己编译的geos实际情况填写,去掉前面的#后,默认的如下

更改前:
#GEOS_DIR=C:/warmerda/geos
#GEOS_CFLAGS = -I$(GEOS_DIR)/capi -I$(GEOS_DIR)/source/headers -DHAVE_GEOS
#GEOS_LIB     = $(GEOS_DIR)/source/geos_c_i.lib

更改后,需要核对geos的根目录位置,根目录下的include文件夹,和geos_c_i.lib文件所在位置,进行具体修改,否则会提示连接失败,或者geos里面的头文件找不到情况。改动如下两点:
GEOS_CFLAGS 变量里面增加-I$(GEOS_DIR)/include
GEOS_LIB变量source更改为src, $(GEOS_DIR)/src/geos_c_i.lib

//更改后:
GEOS_DIR=E:\Lib\geos-3.5.2
GEOS_CFLAGS = -I$(GEOS_DIR)/capi -I$(GEOS_DIR)/include -I$(GEOS_DIR)/source/headers -DHAVE_GEOS
GEOS_LIB     = $(GEOS_DIR)/src/geos_c_i.lib

三、设置OpenCL库

在这个配置前需要检查CUDA是否安装成功,如果没有安装成功则进行安装CUDA后再进行配置。我是直接用everything搜索本地NVIDIA GPU Computing Toolkit,由于我已经安装过,此处省略cuda的安装细节了。

3.1、修改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/v10.0"
OPENCL_CFLAGS = -I$(OPENCL_DIR)/include -DHAVE_OPENCL
OPENCL_LIB    = $(OPENCL_DIR)/lib/x64/OpenCL.lib
!ELSE
OPENCL_DIR=
OPENCL_CFLAGS = -I
OPENCL_LIB     = 
!ENDIF

注意OPENCL_LIB的设置,网上一般看到的是:

OPENCL_LIB    = $(OPENCL_DIR)/lib/Win32/OpenCL.lib

我在实际编译过程中总是提示错误如下:

  正在创建库 gdal_i.lib 和对象 gdal_i.exp
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clGetPlatformIDs,该符号在函数 get_device 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clGetDeviceIDs,该符号在函数 get_device 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clGetDeviceInfo,该符号在函数 GDALWarpKernelOpenCL_createEnv 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clCreateContext,该符号在函数 GDALWarpKernelOpenCL_createEnv 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clReleaseContext,该符号在函数 GDALWarpKernelOpenCL_deleteEnv 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clCreateCommandQueue,该符号在函数 GDALWarpKernelOpenCL_createEnv 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clReleaseCommandQueue,该符号在函数 GDALWarpKernelOpenCL_deleteEnv 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clCreateBuffer,该符号在函数 alloc_pinned_mem 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clReleaseMemObject,该符号在函数 GDALWarpKernelOpenCL_runResamp 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clGetSupportedImageFormats,该符号在函数 set_supported_formats 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clCreateProgramWithSource,该符号在函数 get_kernel 中被引 用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clReleaseProgram,该符号在函数 get_kernel 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clBuildProgram,该符号在函数 get_kernel 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clGetProgramBuildInfo,该符号在函数 get_kernel 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clCreateKernel,该符号在函数 get_kernel 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clReleaseKernel,该符号在函数 GDALWarpKernelOpenCL_deleteEnv 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clSetKernelArg,该符号在函数 GDALWarpKernelOpenCL_runResamp 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clGetKernelWorkGroupInfo,该符号在函数 GDALWarpKernelOpenCL_runResamp 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clFinish,该符号在函数 GDALWarpKernelOpenCL_createEnv 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clEnqueueReadBuffer,该符号在函数 get_dst_rast_data 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clEnqueueMapBuffer,该符号在函数 alloc_pinned_mem 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clEnqueueNDRangeKernel,该符号在函数 execute_kern 中被引用
gdalwarpkernel_opencl.obj : error LNK2019: 无法解析的外部符号 clCreateImage2D,该符号在函数 set_coord_data 中被引用
C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.0/lib/Win32/OpenCL.lib : warning LNK4272:库计算机类型“X86”与目 标计算机类型“x64”冲突
gdal200.dll : fatal error LNK1120: 23 个无法解析的外部命令
NMAKE : fatal error U1077: “"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\amd64\link.EXE"”: 返回代码“0x460”
Stop.

经过分析是因为静态库没有加载成功,查看静态库目录下有个x64的文件夹,更换过来,该问题消失

OPENCL_LIB    = $(OPENCL_DIR)/lib/x64/OpenCL.lib
第二处(增加)

然后在上面那行代码(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)。
在这里插入图片描述

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

makefile.vc文件位置是在根目录的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的库路径设置的是否正确,如果路径中有空格,同样用双引号括起来。

四、GDAL编译

启动VS2015的 x64 本机工具命令(我用VS2013本机工具命令编译的时候报了一个编译器的lib找不到,所以后面用VS2015进行编译通过的)

启动编译前,需要把目录切换到gdal安装包根目录,再进行下面编译,如下图:

在这里插入图片描述

依次运行下面三条命令,实际运行的时候一条条执行,只要分号前面的命令即可

nmake -f makefile.vc MSVC_VER=1900 WIN64=1;//编译

nmake -f makefile.vc MSVC_VER=1900 WIN64=1 install;// 生成bin、data、html文件夹

nmake -f makefile.vc MSVC_VER=1900 WIN64=1 devinstall; //devinstall生成lib和include(其实)

一般第一条编译命令可能出错,兵来将挡水来土掩,我在这里耗了一会,坑已经在上面都说完了。只要第一条编译命令通过后,下面两条命令执行比较顺利。执行完后检查前面设置的GDAL_HOME文件夹下的结果,如下图:
在这里插入图片描述
bin文件夹里gdal202.dll顺利生成了,这时候可以去geos文件夹的src子文件夹把所有的dll拷贝到gdal输出文件夹下的bin文件夹,geos文件夹的src子文件夹下的静态lib文件拷贝到gdal输出文件夹下的lib文件夹。这样就编译成功了。

五、GPU内存泄漏问题解决

最后进行效果测试,运行的时候CUDA内存用起来了,但是后面控制台出现了一些错误提示,查看输出的结果影像,有时候没有问题,有时候也会导致影像损坏的情况(如下图),关于这个控制台的错误经过分析,可能因为没有释放,导致显存超出了。显存复制数据出错导致的。

1、开始运行,没有错误提示,硬盘读写速度也较快
开始运行,没有错误提示,硬盘读写速度也较快
2、观察GPU显存占用情况不断升高,当进度为50%左右的时候显存占满了
在这里插入图片描述

3、当显存占完后,控制台出现错误提示,硬盘读写速度明显卡顿了
在这里插入图片描述

4、输出影像有损坏在这里插入图片描述

为了解决这个问题先检查了源代码,没有发现可以手工释放内存的地方,于是想着可能是gdal版本问题。
下载了gdal2.4.4按照上面方法重新编译了一遍,GPU内存泄漏问题消失。

啥,你问我为啥不用更高版本的gdal ?
答:我也试过gdal3.0及以上版本,3.x版本的gdal编译起来比较困难,必须要依赖proj6.0及以上版本,尝试了proj6.0以上版本编译,总是有问题,所以退而求其次,使用gdal2.4.4版本,该问题解决了就行了。

2022.5.4 初版
2022.5.6 增加GPU 内存泄漏问题解决方案(提供编译的程序下载)。使用gdal2.4.4可以解决该问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值