1.原子操作
熟悉操作系统的读者对与原子操作不会陌生,原子操作代表不可被分割的操作,也就是最小的计算机可执行程序的单元。在CUDA中,也有这样的原子操作,我们使用原子操作之后,会锁定空间,防止其他的进程访问。由于CUDA的超多线程并行运算的特性,我们可以利用CUDA中的原子操作来优化我们的程序。
1.1 CUDA原子操作
CUDA可供使用的原子操作有很多,我们只介绍最基本的一个atomicAdd
,这个函数接受两个同类型的参数,并将第二个值加到第一个值上。我们举一个简单的直方图统计的例子来说明在什么情况下使用原子操作。
1.2 直方图统计GPU版:
我们现在有一个很长的字符串,我们要统每个字符的出现次数。如果利用CPU进行计算,我们会在很长的时间来遍历一遍字符串。利用CUDA,我们可以将整个任分配给多个进程块,或者我们可以启动一个256个进程组成的进程块。总之,我们发现进程块的数量是CUDA单元的2倍时,效率是最高的。我们之后可以利用原子操作来执行对应的任务。
但是我们开率这样一个问题,当有很多个原子操作时,内存是有限的,当有很多个原子操作试图访问比较小的全局内存的时候,反而会因为信号竞争产生大量的堵塞,这个时候我们需要用上回讲到的共享内存了。
我们首先分配同样大小的共享内存,然后先讲这个进程处理的值暂存在共享内存。之后我们在把他们合并在一起。同样的,我们要在全部的初步统计结束之后,让所有的线程同步。当然,同步的过程同样使用原子操作。
使用原子操作的确会加快速度,有的时候增加更多的原子操作未必是件坏事。