CUDA计时
写cuda程序的时候需要对kernel进行计时有一套模板,不费话直接奉上
cudaEvent_t start,stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start);
//接下来是需要计时的代码块
//---------------
//---------------
cudaEventRecord(stop);
cudaEventSynchronize(stop);
float elapsed_time;
cudaEventElapsedTime(&elapsed_time,start,stop);
printf("now this cuda pro exe time is %g ms.",elapsed_time);
cudaEventDestroy(start);
cudaEventDestroy(stop);
首先定义两个cuda事件,然后对stop和start进行初始化,而后利用EventRecord事件对start计时,需要计时代码块执行结束后我们开始记录用record来记录stop函数。然后定义个elapsed_time,用cudaEventElapsedTime来获得执行时间。
GPU加速关键因素
- 数据传输比例:
在GPU计算需要先把数据从CPU传输到GPU,这个过程的事件开销比较大,而且我们如果要执行较为简单的程序时可能事件开销还比不过CPU。GPU和CPU数据传输的带宽明显比CPU内部传输的带宽低,所以我们如果想获得GPU加速,就必须缩减数据传输所花时间的比例。
如果我们只执行一次的数据相加的计算,那么我们传入GPU所花时间可能跟GPU执行的时间是差不多的。。。 - 算数强度:
这里就是根据GPU的显存带宽,因为每次在取数据和存数据的过程中都花费了大量的时间。 - 并行规模
并行规模可以用GPU中的总线程数目来衡量。从硬件角度看GPU是有多个SM构成的,每个SM有若干CUDA核心,而且每个SM都是相对独立的。从开普勒到伏特架构每个SM中可以驻留的thread为2048个,图灵架构是1024个。一个GPU有几个到几十个SM,所以一个GPU可以驻留几万到几十万个thread,如果一个kernel中的定义的thread数目元小于这个,那很难得到很高的加速比。
总结
所以一个CUDA程序获得较高的性能的必要条件有:
- 数据传输比例较小
- 核函数的算数强度高
- 核函数中定义thread数目足够多
那么我们在编写和CUDA程序的时候主要做到:
- 减少host和device的数据传输
- 提高核函数的算数强度
- 增大核函数的并行规模