用户
 找回密码
 立即注册
十四王爷 该用户已被删除
发表于 2016-7-8 10:35:49
216080
写在前面内容分为两部分,第一部分为翻译《Professional CUDA C Programming》 Section 2. CUDA Programming Model中的TIMING YOUR KERNEL;第二部分为自己的经验。经验不足,欢迎各位大大补充。
写CUDA,追求的就是加速比,想要得到准确的时间,计时函数就是必不可少
计时通常分为两种情况,(1)直接得到接口函数的时间,一般用于得到加速比;(2)获得接口函数内核函数、内存拷贝函数等所耗时间,一般用于优化代码时。
情况(1)方法有两种,CPU计时函数和GPU计时函数。
情况(2)有三种工具nsight,nvvp,nvprof
本文会详细介绍情况(1)的两种方法;情况(2),nsight不会用,简单介绍一下nvvp和nvprof的用法。
CPU计时函数
在利用CPU计时函数时,要考虑的一个问题是:核函数的执行是异步执行的,所以必须加上核函数同步函数,才能得到准确的时间。
示例代码如下:
  1. double cpuSecond() {
  2.     struct timeval tp;
  3.     gettimeofday(&tp,NULL);
  4.     return ((double)tp.tv_sec + (double)tp.tv_usec*1.e-6);
  5. }
  6. double iStart = cpuSecond();
  7. function(argument list);
  8. cudaDeviceSynchronize();  // 同步函数
  9. double iElaps = cpuSecond() - iStart;
复制代码
GPU计时函数
GPU计时函数就不需要考虑同步问题,直接用计时事件函数就可以了,示例代码如下:
  1. cudaEvent_t start, stop;
  2. float elapsedTime = 0.0;

  3. cudaEventCreate(&start);
  4. cudaEventCreate(&stop);
  5. cudaEventRecord(start, 0);

  6. function(argument list);;

  7. cudaEventRecord(stop, 0);
  8. cudaEventSynchronize(stop);

  9. cudaEventElapsedTime(&elapsedTime, start, stop);

  10. cout << elapsedTime << endl;

  11. cudaEventDestroy(start);
  12. cudaEventDestroy(stop);
复制代码
如何获得精确的计时正常情况下,第一次执行核函数的时间会比第二次慢一些。这是因为GPU在第一次计算时需要warmup。所以想要第一次核函数的执行时间是不精确的。获得精确的计时我总结为三种,如下
  • 循环执行一百次所需要计时的部分,求平均值,将第一次的误差缩小100倍。这种方法的优点是简单粗暴。但缺点也很明显:(1)程序的执行时间大大增长,特别是比较大的程序(2)要考虑内存溢出问题,C++的内存需要程序猿自己手动管理。写出执行一次不出内存溢出问题的程序很容易,但是写出循环执行一百次而不出内存溢出问题的代码就有一定难度了(3)计时不是特别准确,虽然误差已经被缩小了100倍。
  • 在计时之前先执行一个warmup函数,warmup函数随便写,比如我从cuda sample里的vectoradd作为warmup函数。这种方法的优点是程序执行时间缩短;缺点是需要在程序中添加一个函数,而且因为GPU乱序并行的执行方式,核函数的两次执行时间并不能完全保持一样。所以推荐使用方法3.
  • 先执行warmup函数,在循环10遍计时部分。


nvvp和nvprof的用法
nvprof是自cuda5.0开始存在的一个命令行Profiler,你可以只用nvprof来你代码的一些执行细节。简单用法如下:
  1. $ nvprof ./sumArraysOnGPU-timer
复制代码
你就可以得到如下:
  1. ./sumArraysOnGPU-timer Starting...
  2. Using Device 0: Tesla M2070
  3. ==17770== NVPROF is profiling process 17770, command: ./sumArraysOnGPU-timer
  4. Vector size 16777216
  5. sumArraysOnGPU <<<16384, 1024>>> Time elapsed 0.003266 sec
  6. Arrays match.
  7. ......
复制代码
关于nvprof的更多参数信息,可以使用帮助命令:
  1. $ nvprof --help
复制代码
The NVIDIA Visual Profiler(nvvp是一款图形化界面的Profiler,也是我一直在用的Profiler。

本文来自大光叔叔的原创,http://blog.csdn.net/litdaguang/article/details/50520549



使用道具 举报 回复
发新帖
您需要登录后才可以回帖 登录 | 立即注册