CUDA编程——Mars:MapReduce on GPU

CUDA编程——Mars:MapReduce on GPU


1 GPU加速机器学习

  GPU是一种SIMT(单指令多线程)体系结构,即多个线程执行同一个指令,而每个线程操作的数据不同。这种结构令GPU天生具有大规模计算能力。GPU出色的浮点计算性能特别提高了深度学习两大关键活动:分类和卷积的性能,同时又达到所需的精准度。深度学习需要很高的内在并行度、大量的浮点计算能力以及矩阵预算,而GPU可以提供这些能力,并且在相同的精度下,相对传统CPU的方式,拥有更快的处理速度、更少的服务器投入和更低的功耗。NVIDIA介绍,TITAN X在工业标准模型AlexNet 上,花了不到三天的时间、使用 120万个 ImageNet 图像数据集去训练模型,而使用16核心的 CPU 得花上四十多天。更震撼的是使用 NVIDIA推出的DIGITS DevBox [1]来训练 AlexNet 则只要13个小时就能完成。
  然而,这种庞大的并行能力需要付出代价:必须编写专门的软件才能利用这样的优势,GPU编程相对于CPU编程需要更多程序员的付出。目前GPGPU的程序模型仍不成熟,将数据划分为不同粒度,送到GPU的每个流处理器(SP)运算,这些工作仍需要程序员手工完成。此外,由于GPU不具有分支预测等复杂的流程控制单元,对于高度分支的程序执行效率差。GPU核心是虚拟化的,线程调度由硬件完成,无法动态调度。程序员需要避免写有高度分支的程序。GPU由于没有足够大的cache,读写主存导致latency。程序员需要利用大量线程隐藏latency。另外不同厂商的GPU硬件架构不同,用户可以获得的细节有限。这些都导致在GPU上设计通用的计算框架,仍然具有很大挑战。




2 Mars

  近来,一些GPGPU 编程框架被提出,如NVIDIA的CUDA和AMD的Brook+,这些框架大大提升了GPU可编程性。Wenbin Fang等认为这些编程语言的接口依赖与特定厂商,并且他们的硬件抽象不适合于开发复杂应用。所以提出了一个易于在GPU上编程的MapReduce框架[2]。Mars框架可以用在分布式环境中,如hadoop。Mars可以应用在多核CPUs,NVIDIA GPUs,AMD GPUs或者联合一个多核CPU和一个GPU的单机上。Mars解决了三个技术挑战:首先MapReduce根据数据分割任务,利用GPU执行大量并行线程时,负载不平衡是一个固有问题,特别是GPU的线程由硬件管理。其次,GPU缺乏有效的全局同步机制,Map或Reduce任务中的线程在输出缓存上常常发生写入冲突。尽管GPU现在已经支持原子操作,原子操作的缺陷却会伤害大量GPU线程的可扩展性[3]。Mars提出一个lock-free调度方法来减少GPU线程同步带来瓶颈。第三,MapReduce应用通常是数据密集,且结果的规模也是依数据而变。这两个特性导致GPU编程有以下需求:1)足够多线程隐藏内存延迟,充分利用设备内存的高带宽。2)预先在设备内存上分配输出缓冲区,利用DMA减少内存存取时间。Mars中,有大量thread在GPU上并行运行,每个thread一次运算一个key/value pair,在Map阶段,框架平均分配key/value pairs到每个thread,Reduce阶段,Mars使用一种简单但高效的倾斜算法重新分配数据到Reduce任务,达到负载均衡。为了避免多线程写入冲突,Mars采用了一种lock-free策略保证并行程序的正确,仅付出很小的同步代价。


2.1 Mars 工作流程

  Mars的工作流程如下图。



  以Mars的word count为例,Mars读取文件,将文件切分为ceil(2048)大小的一块,这里的ceil(2048)是指≥2048字符长度的连续字符,即块以非空字符开始,结尾是偏移≥2048字符长度的第一个空字符的前一位。每一块分配给一个GPU thread,256个thread组成一个block,多个block组成一个grid,一次GPU内核函数调用执行一个grid。从调度和运行方式看,GPU上block概念和CPU上的进程很相似,一个进程占用一个CPU核运行,多个进程轮转调度;一个block占用一个GPU SM运行,多个block轮转调度。从这个角度看,GPU的SM很像GPU核。


2.2 MapSplit

  假设原始数据放在磁盘上,Mars利用CPU程序从磁盘读取数据,将输入转换为key/value pairs保存在主存中,之后传输到GPU设备内存。MapSplit阶段,将输入分配给GPU thread,分配的方式是一种分段式扫描的方式。
  分段扫描,就是对数据集进行有规律的扫描操作(最大值,最小值,总和等),并附带一个额外的数组,将原来的数组分成不同大小的块。每块分配一个或多个线程进行计算。由于附加的数组可以在运行时进行更新,因此如果分段扫描能保持在一个单独的线程块内执行,就可以减少调用多内核的需要。否则,则需要采用一种更简单的解决办法。分段式扫描能够在多数情况下正常工作,并且线程和线程块的数量能随着并行度增加或缩减灵活改变。


2.3 MapCount

  MapCount用于计算Map输出的中间结果的大小,以便预先分配GPU内存,计算方式是通过求前缀和(Prefix Sum)获得输出大小和每个线程写入数据的位置。前缀和也叫累积和,一组数序列 x0,x1,x2

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值