洪 亮,周松涛,罗 伊,石婷婷,胡 飞
(1.湖北省航测遥感院,湖北 武汉 430074;2. 武汉大学 国际软件学院,湖北 武汉 430070;3. 湖北省基础地理信息中心,湖北 武汉 430074;4.安陆市国土资源局,湖北 安陆 432600)
遥感数据多为图像数据,对它们的处理涉及大量特征数据的计算、统计等。对这些数据的运算往往是基于分块的算法,即将栅格数据的局部按某种经纬格网裁剪出来进行计算,然后将结果写回数据库。在单一工作站上,这一运算往往是一个串行的过程,因此效率比较低。目前的高性能计算主要是采用并行计算技术来实现[1]。在硬件体系结构上,并行计算机主要分为3种形式:多处理机系统、多计算机系统和集群计算技术。但考虑到成本、安全及使用频度、运算效率等问题,基于网络的多计算机系统和集群运算并不合适,而简单的多处理机系统运算能力有限。基于GPU的加速计算技术为海量遥感数据处理效率的提高带来了新的手段。GPU最初是针对图形渲染,但在其上的通用计算技术显然非常适合类似于图像这类数据的计算与处理。在面向GPU的通用计算技术中,CUDA技术是发展最早、目前相对完善、普及的一种技术。
与早期的图形处理器不同,现代的图形处理器往往具有可编程单元,用于处理庞大而复杂的三维图形数据。通常,一个GPU内部有两个可编程单元,即顶点着色器和像素着色器,这两个单元包含有几十个甚至几百个流处理器,可并行处理图形的顶点和像元数据,有很强的浮点运算能力。目前国际上两大图形处理器厂商——NVIDIA和AMD,都在自己的GPU基础上,构建了一套通用数学运算的机制,即NVIDIA的CUDA技术和AMD的STREAM技术,其中CUDA技术应用比较成熟和广泛[2]。
CUDA是一个通用的并行计算架构,将GPU强大的并行计算能力充分调动起来,使之在解决复杂计算问题上发挥其先天优势。开发人员仅使用C语言,就能在基于CUDA架构的GPU上编写程序,在支持CUDA的处理器上以超高性能运行。不仅如此,CUDA还是免费的开源技术,任何开发人员都能通过最新的NVIDIA GPU,在个人计算机上实现高性能计算,解决复杂的科学运算问题。
与英特尔的X86架构不同,CUDA基于GPU,但不拘于GPU,而是取长补短,将CPU的串行计算和GPU的并行计算融合,开启“CPU+GPU协同计算”的全新时代,即“异构计算”。“异构计算”真正实现了系统整体计算能力的最大化利用:GPU和CPU协同工作,GPU处理大量的图形和并行处理,CPU处理操作系统和指令的逻辑控制。两者的协同比单纯CPU运算高出几十倍甚至几百倍、上千倍,使得PC和工作站具有超级计算的能力,使得个人超级计算机的普及成为可能。
目前,采用GPU进行通用运算越来越普及,一些常用软件,如Photoshop、3DMax以及一些视频处理软件已大量使用该技术。从应用的效果来看,均有几倍或几十倍的效率提升,前景非常广阔。有鉴于此,在GPU基础上,NVIDIA又进一步开发了Tesla处理器。该处理器外观跟显卡非常相似,只是没有显示输出接口。这种“显卡”的主要作用就是“多块并联”,通过CUDA来进行科学运算。和传统服务器/工作站相比,塔式Tesla主机也有CPU等常规硬件,只是内部有多块“显卡”组多路SLI,如图1所示。通过Tesla处理器构建的个人高性能计算机,利用多路显卡的强大并行处理能力,使一些以往主要依靠CPU计算的领域大大提速,甚至使部分依靠CPU无法完成的计算成为可能。
图1 带有Tesla处理器的个人超级计算机
图2 CUDA中运算任务的逻辑划分
GPU作为一种图形运算单元,具有对纹理图像的各种优化运算功能,支持栅格数据的并行运算。
在CUDA运算中,每个GPU的运算单元被映射成一个网格(Grid),每个网格单元在逻辑上被分为多个Block,每个Block被分为若干Thread,Thread作为最新运算逻辑单元存在(如图2)。在与硬件的对应关系上可以近似地认为,每个网格对应一个GPU(或一块Tesla处理器),一个Block对应一个SM(streaming multiprocessor),而一个Thread则对应硬件上的一个运算单元,即一个SP(streaming processor)。之所以说这种对应关系是近似的,是因为为了防止在I/O等过程中运算单元闲置,GPU会对不同的任务分组进行优化处理和调度。例如在一个Block中,32个Thread会被分为一组并执行,称为一个Wrap。如果发生任务闲置的情况,则换另外一组,从而导致Thread和SP之间并没有严格的一一对应关系。
可参照这一逻辑模型对栅格数据分块进行处理。可参照栅格数据的逻辑模型(一个2维矩阵),将栅格数据作2维的逻辑任务划分,与图2中所示模型一致。实际应用中,栅格数据的块状划分可根据应用情况进行处理。例如,一些空间数据库在对栅格数据存储过程中进行了分块索引,那么检索到客户端的栅格数据也是自然分块的。分析处理中,这个数据块可根据其大小,映射到一个Grid单元或一个Block单元进行计算,避免对栅格数据的重新规划以及重新分块。
在一个Block内部,涉及到如何将一块栅格数据分布到不同的Thread中执行运算的问题。实际操作中,这一部分的划分不是按照矩阵的逻辑模型,而是按照条带的方式,即将一个数据块中的不同行放到不同的Thread中进行处理。同一行数据以及相邻行数据在存储空间连续,便于地址空间的管理,也便于运算结果的写回。
在CUDA中,与开发者密切相关的存储器类型主要有两种,即全局存储(global memory)和共享存储(shared memory),见图3。全局存储是在一个运算设备上全局共享存储区域,一般来讲就是显存的一部分,用户与CUDA之间的数据传输可通过这部分存储区间完成。图3中,Host是用户在CPU中执行的代码。共享内存是在一个Block中共享存储区域,其作用可看作是高速缓存,存取速度虽然很快,但大小受限,在目前的硬件水平上一般不超过16 K。在栅格数据的任务调度中,尽量将数据放到共享存储区域进行处理,这样效率会较高。在CUDA模型中,将数据放到共享存储区域的过程是一个需要用户干预的过程。用户在开发过程中,需要指定全局存储中的数据如何组织到共享存储中。CUDA的内建函数也提供了一些指令,用于不同线程间共享存储数据的同步。
采用CUDA技术进行海量数据的并行运算,其效率除了受并行线程数量影响以外,还受存储器的访问效率影响。GPU访问显存的效率要远远高于CPU访问内存的效率,主要是因为它在带宽和频率上都要高于CPU所在系统的总线。而在CUDA层面,对数据的访问则可以考虑全局和共享存储两个层面。对于单个线程,在计算比较复杂、涉及的数据量大时,可不使用共享存储单元;而在运算简单、数据运算局部性比较强时,可先将一个Block中的线程需要访问的数据组织到共享存储单元中,然后再以共享存储单元的访问为基础进行计算。
图3 CUDA的存储模型
上述存储及调度模型是基于单机任务的,如果存在海量遥感数据,则需要在单机模式基础上,建立一个支持分布式或在单一节点上存在多处理器的分布式运算模型[3,4]。
在一个基于GPU的运算集群环境下,栅格数据处理任务划分可参照图4中的逻辑模型,将栅格数据作2维的逻辑任务划分。栅格数据的块状划分可根据应用情况进行处理。例如,一些空间数据库在对栅格数据存储过程中进行了分块索引,那么,检索到客户端的栅格数据也是自然分块的。分析处理中,这个数据块可根据其大小映射到一个GPU设备(即一个Grid)单元或一个线程块(Block)单元中进行计算,从而避免对栅格数据的重新规划以及重新分块处理[5]。
图 4 海量栅格数据在分布式环境下任务处理的逻辑模型
图4中,假设有4个运算节点工作站对数据库中的栅格数据进行处理。为了避免重新对数据进行任务划分,可令每个节点计算机处理一块数据。在获取到数据后,节点计算机可根据其自身处理能力对数据进行再次划分。例如,运算节点1中包含有运算能力不同的两个处理单元,则在任务划分中,将待处理数据按运算能力的大小分为两个部分。实际处理中,这种划分仅仅是一个偏移地址的处理,处理时间可以忽略不计。
为了客观评价CUDA技术在栅格数据加速运算过程中的效率,本文分别通过相关曲面、Sobel算子以及标准差计算来比较[6-8]。
由于相关曲面模板大小为可变的,且其宽和高往往较一般卷积算子大,受共享存储单元大小的限制,不便于放在其中运算。因此,这部分的测试是基于全局存储访问进行的。测试过程中,在不同尺寸的数据和匹配模板下分别用CPU和GPU进行计算,并比较二者的效率,见表1。
表1 GPU和CPU环境下相关曲面计算比较
从表中可以看出,在数据量比较小的情况下,GPU计算并无多大的优势。随着数据量的加大,GPU相对于CPU计算的加速比逐渐变大。可见,在海量栅格数据的处理中,GPU通用计算的优势非常明显。
这一测试的目的是检测基于GPU的全局存储和共享存储进行计算的差别,因此,Sobel算子的测试并没有在CPU下进行运算测试。由于Sobel算子卷积的运算量较小,运算速度较快,为了使结果比较客观,两种卷积运算各循环运算100次,然后求平均值。
在GPU采用Geforce GT 420 M的条件下,计算Sobel算子全局存储访问运算的平均时间为0.000 023 s,共享存储访问的平均时间为0.000 017 s,共享存储访问方式下的运算效率要高于全局存储。因此,对于栅格数据的相关算法,应尽量寻求在共享存储访问模式下运算,以充分发挥GPU的优势。
为了反映未进行任务划分条件下CPU和GPU计算能力的差异,对一个数组进行标准差统计。测试中,分别在CPU单线程、GPU单线程以及GPU多线程条件下进行。其中,GPU单线程指的是未对任务进行任何划分,直接把整块数据放到GPU中运算,同一时刻只有GPU的一个运算单元参与;GPU多线程则是将计算平均值以外的部分进行并行计算。数组大小为5 000个浮点数,计算结果见表2。
表2 标准差计算在不同计算条件下的时间比较
由此可见,如果不对任务进行划分,单纯靠GPU本身对任务调度计算,其计算能力甚至远远落后于CPU。仅对其中一部分的计算适当并行,GPU计算的效率则有明显改观。但是,标准差的计算是一个基于全局的运算,整个算法在实现过程中只有部分可实现并行计算,因此,类似算法如果要提高效率,还需要在算法上进行重构,不能仅仅依靠硬件性能。
另外,一次运算的数据规模也是影响运算效率的因素之一。GPU运算不像CPU,首先需要将运算数据传输到GPU存储器(显存),并进行一些数据结构的准备,再启动内核计算。这些必要工作同样消耗运行时间,而且与运算规模无关。因此,在GPU中进行数据处理,输入规模越大,GPU中可并行的线程就越多,并行运算优势就越明显。图5是CPU和GPU并行计算效率的比较,横坐标表示运算规模,纵坐标表示时间消耗,单位为s。可见,当输入数据量在131 072(即217)左右时,CPU和GPU耗时相当;大于217时,GPU表现出时间上的优势。
图5 不同运算规模下标准差计算的CPU-GPU效率比较
本文实验证实,在海量栅格数据处理中,GPU通用计算技术确有优势。因此,适当地改良现有栅格数据的算法,使之适应于GPU通用运算环境,是提高栅格数据运算效率的有效途径。但是,由于GPU架构以及开发形式的特殊性,实际应用中往往很难使程序具有通用性,尤其是在大规模并行计算的环境下,而硬件条件往往比较统一,在允许的情况下可针对特定的GPU硬件进行优化,以达到效率最大化。
[1]Kirk D B,Hwu W W.大规模并行处理器编程实战[M].北京:清华大学出版社,2010
[2]张舒,禇艳利.GPU高性能运算之CUDA[M].北京:水利水电出版社,2009
[3]Sanders J, Kandrot E.CUDA范例精解——通用GPU编程[M].北京:清华大学出版社,2010
[4]多相复杂系统国家重点实验室多尺度离散模拟项目组. 基于GPU的多尺度离散模拟并行计算[M].北京:科学出版社,2009
[5]林一松,杨学军,唐滔,等. 一种基于关键路径分析的CPUGPU异构系统综合能耗优化方法[J].计算机学报,2012(1):123-133
[6]卢风顺,宋君强,银福康,等.CPU/GPU协同并行计算研究综述[J].计算机科学,2011(3):5-9
[7]许洪腾.图像变换与表示技术及其在影像资料修复与增强中的应用[D].上海:上海交通大学, 2013
[8]卢丽君,廖明生,张路.分布式并行计算技术在遥感数据处理中的应用[J].测绘信息与工程,2005,30(3):1-3