技术开发 频道

NvidiaCUDA通用计算简介及优化方法概述

  2. nVidia GPU简介

  第一款被称作可编程的GPU是NVIDIA的NV20,就是传说中的Geforce3,不过它远远不能对CPU的地位构成威胁。它能够处理的程序指令还非常有限,大约在10条左右,另外它所能处理的数据类型也非常之有限,只能处理9或12bit固定长度的数据。当NVIDIA的NV30发布的时候,摩尔定律再次得到了印证,不仅仅是晶体管数量的增加,计算单元的数量也成倍增长。同时这也使得显卡芯片更具灵活性。因此NVIDIA的NV30具备许多革命性的突破。从NV30起,GPU开始支持单精度浮点运算,即使它并不完全支持IEEE754标准,

  2.1 G80架构

  主要包括2006年11月发布GeForce 8800,500 GFLOPS,2008年4月发布的GeForce 8800 GTX,使用GDDR3 DRAM,每个core有一个单精度浮点乘加,可以进行整数运算,每个SM包括8个core,还包括2个special functional units(SFUs),执行特殊的函数,每个SM包括8096字节寄存器空间,16KB 软件管理的共享内存空间。

  2.2 GT200架构

  主要包括2008年发布GeForce GTX 280,900 GFLOPS,支持双精计算,每个SM一个双精计算单元,共享内存增加为32KB共享内存空间,加入合并全局内存访问,共享存储空间原子操作,每个core的整数逻辑单元(ALU)仅限于24bit的乘法操作

  2.3 Fermi架构

  2010年刚刚发布的Fermi架构,基于CUDA 2.0,主要包括以下特点:支持C++,支持IEEE 754-2008 32位和64位计算,支持ECC,支持cache hierarchy。64位虚拟地址空间,不同memory统一编址。40位线性地址空间。原子操作快20倍。双精度计算速度比GT200快8倍,单精要慢,1.5 TFLOPS单精,750 GFLOPS双精。S2050 3G memory,S2070 6G memory。不同程序切换时间为20到25 微秒。线程切换速度提高10倍,最多支持6GB GDDR5内存,将DRAM分为6块64位,总共384位内存接口,Fermi和PTX 2.0 ISA将分离的线程local memory,线程块shared memory和global memory地址空间统一编址,40位寻址能力。在PTX 1.0中,load/store指令在编译时就指向三种地址空间中一种。

  Tesla C2050,2010年5月发布,包含14个SM,448个core,1.15GHz,双精和单精峰值分别为525GFlops和1.03TFlops。C2050为3G GDDR5内存,C2070为6G GDDR5内存,所有存储层次都支持ECC校验,如果使用ECC,则可用内存减少12.5%。内存频率和位宽分别为1.5GHz和384bit,带宽为144GB/s。使用PCIe x16 Gen2(理论峰值为8GB/s)互联GPU与CPU,支持C/C++/Fortran,OpenCL,DirectCompute。

  32core/SM,共512个core,每个core有一个FPU和一个整数运算单元,每个SM包括以下部分:一个指令cache;16个core为一个计算单元;16个load/store单元(一个clock计算16个线程的地址)和4个SFU。双精度计算需要32个core,因此SM可以同时发送16个双精度计算或者32个单精度计算。每个SM有两个warp scheduler和dispatch unit,每个时钟周期可以调度和发射2个32线程warp。在同一时刻,第一个warp调度器可以发射奇数ID号warp中的指令,第二个调度器可以发射偶数ID号中的指令,唯一的例外是只有一个调度器可以发射双精度指令,此时另一个不能发射指令。因此对一个warp,调度器要用2个cycles来发射一个整数,浮点运算指令或双精度浮点运算指令,用8个cycles发射单精度transcendental指令。而1.x调度器需要4个cycles发射整数和单精浮点运算指令,32个cycles发射双精度运算指令,16个cycles发射单精度transcendental指令。每个时钟周期可以执行16个存储指令。每个SM最多支持16个kernel并行执行。发布的Fermi支持4个kernel并行执行,因为concurrent kernels最大并行数量是由GPC确定的。

  GigaThread将线程块分配到一个SM调度器。每个SM有32K 32-bit寄存器,128KB大小。每个SM可以运行48个warp,1536个线程,32个SM可运行24576个线程。每个SM有64KB空间,可以配置成16KB共享内存加48KB L1 cache,或者配置成48KB共享内存加16KB L1 cache。 768KB统一L2 cache。为某些数据并行度较低而不能产生大量线程以隐藏延迟,或者某些数据重用模式不固定的应用。Fermi寄存器大小为16*128KB=2048KB,L1 cache大小为16*48KB=768KB,L2 cache大小为768KB。而不是传统存储层次距离较远具有较大存储空间。L1和L2中cache line大小为128bytes,映射到global内存128byte对齐段。

  Fermi以前的架构由于没有cache存储层次,并且线程块没有同步机制,所以分配到不同SM的线程块不会引起冲突,由于Fermi引入了2层存储层次,因此性能模型设计和算法优化必须考虑调度到GPU运行的所有线程块间协作,在一段时间内其总体数据量不要超过L2 cache,否则会导致冲突缺失。而由于维护L1 cache coherence开销,所有SM访问写数据应该保持独立,避免不同SM同时写入同一数据。

  由于每个SM有64KB空间,可以配置成16KB共享内存加48KB L1 cache,或者配置成48KB共享内存加16KB L1 cache。对于可以充分利用共享内存的算法,配置为48KB共享内存可以增大GPU整体缓存大小=16*48KB+768KB=1536KB,如果配置为16KB共享内存,则GPU可利用缓存大小最小,为=16*16KB+768KB=1024KB。

  Fermi挑战:面向双精,比单精增加一倍带宽需求。频率增加,计算能力更前,双精515GFLOPS,使得内存墙问题更为严重。为了弥补前面二点,加入了多层存储层次,增加了调优难度。加入更多寄存器,提供更多threads,以更好隐藏延迟。

0
相关文章