編譯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;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章