2 oyangzi12 oYangZi12 于 2016.04.06 21:28 提问

CUDA加速为什么没有并行的效果

我对一幅图像做处理,640X480,对每个像素我分配了一个thread,即我每个block分配了640个thread,分配了480
个block。然后我对另一幅2048X1536的图像操作,我每个block分配了1024个thread,共分配了1536X2个block。用
同样的算法,问题规模增加了10倍,我不理解的是为什么运行时间也增加了10倍。不是只会增加一点读取数据的时间吗。
对CUDA的运行原理不是很了解,忘大神指教。图片说明

3个回答

sunmc1204953974
sunmc1204953974   2016.04.06 21:52

CUDA编程的优化可不只是一味增加线程,线程增加到一定程度就不能加速了,反而会越来越慢,因为实际上GPU的处理单元还是有限的,增大线程只能在一定程度上隐藏global memory的latency,题主最好去系统学一下CUDA,不然写出来的程序是比较差的,常规的优化方法还有非常多,要想优化好一个CUDA程序,首先要设计比较合理的并行算法,举个例子来说树状加法并行就会比正常相加快很多,第一步是首先尽量优化内存带宽,因为内存带宽一般是程序的瓶颈,GPU相比CPU的一大优势就在于有非常大的内存带宽,有的能到150GB/s,这里面不单单是线程,比如考虑访问global内存的顺序,如果是顺序访问内存,而不是跳跃访问,大概会有3-8倍的加速,在线程方面使用基本没有latency的share memory 也是一个加速的手段,优化好内存带宽之后还有很多的优化技术,比如优化指令流,在误差可接受的情况下,使用CUDA算术指令集中的快速指令,避免多余的同步,资源均衡,与主机通信优化,尽量减少CPU与GPU间的传输,使用流和异步处理隐藏与主机的通信时间;使用zero-memory技术和Write-Combined memory提高可用带宽等等,所以建议去系统学一下,还是很有学问的~

sunmc1204953974
sunmc1204953974   2016.04.06 22:35

关于为什么线程不能这么多的问题,我说的不是很清楚,我再补充一下,支持CUDA的NVIDIA 显卡,都是由多个multiprocessors 组成。每个 multiprocessor 里包含了8个stream processors,其组成是四个四个一组,也就是两组4D的处理器。

每个 multiprocessor 还具有 很多个(比如8192个)寄存器,一定的(比如16KB) share memory,以及 texture cache 和 constant cache

在 CUDA 中,大部份基本的运算动作,都可以由 stream processor 进行。每个 stream processor 都包含一个 FMA(fused-multiply-add)单元,可以进行一个乘法和一个加法。比较复杂的运算则会需要比较长的时间。

在执行 CUDA 程序的时候,每个 stream processor 就是对应一个 thread。每个 multiprocessor 则对应一个 block。但是我们一个block往往有很大量的线程,题主用到了640个和1024个,远超一个 multiprocessor 所有的8个 stream processor 。

实际上,虽然一个 multiprocessor 只有八个 stream processor,但是由于 stream processor 进行各种运算都有 latency,更不用提内存存取的 latency,因此 CUDA 在执行程序的时候,是以warp 为单位。

比如一个 warp 里面有 32 个 threads,分成两组 16 threads 的 half-warp。由于 stream processor 的运算至少有 4 cycles 的 latency,因此对一个 4D 的stream processors 来说,一次至少执行 16 个 threads(即 half-warp)才能有效隐藏各种运算的 latency。也因此,线程数达到隐藏各种latency的程度后,之后数量的提升就没有太大的作用了。

还有一个重要的原因是,由于 multiprocessor 中并没有太多别的内存,因此每个 thread 的状态都是直接保存在multiprocessor 的寄存器中。所以,如果一个 multiprocessor 同时有愈多的 thread 要执行,就会需要愈多的寄存器空间。例如,假设一个 block 里面有 256 个 threads,每个 thread 用到20 个寄存器,那么总共就需要 256x20 = 5,120 个寄存器才能保存每个 thread 的状态。

而一般每个 multiprocessor 只有 8,192 个寄存器,因此,如果每个 thread 使用到16 个寄存器,那就表示一个 multiprocessor 的寄存器同时最多只能维持 512 个 thread 的执行。如果同时进行的 thread 数目超过这个数字,那么就会需要把一部份的数据储存在显卡内存中,就会降低执行的效率了。

wangyaninglm
wangyaninglm   Ds   Rxr 2016.04.07 11:39

数据上传下载也要开销的,主要看看代码咋写的才好说

oYangZi12
oYangZi12 我看了下传数据的时间几乎可以忽略
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!