【问题标题】:Calculating time using clock gives value as zero - linux使用时钟计算时间的值为零 - linux
【发布时间】:2012-05-09 20:44:53
【问题描述】:

我有一个在 GPU 上执行计算的 cuda 代码。 我正在使用时钟();找出时间

我的代码结构是

__global__ static void sum(){

// calculates sum 
}

extern "C"
int run_kernel(int array[],int nelements){
 clock_t start, end;
  start = clock();
  //perform operation on gpu - call sum
 end = clock();
 double elapsed_time = ((double) (end - start)) / CLOCKS_PER_SEC;
 printf("time required : %lf", elapsed_time);
}

但时间总是 0.0000 我检查了打印开始和结束时间。开始有一些价值,但结束时间总是零。

知道可能是什么原因吗?测量时间的任何替代方法。

任何帮助将不胜感激。

谢谢

【问题讨论】:

  • elapsed_time 零还是end 零?我想你使用的是 GPU 而不是 CPU,所以测量 CPU 时间不会给你 GPU 时间。
  • 也许你测量的时间小于时钟的粒度?尝试在 start=clock() 和 end=clock() 行之间临时打一个 sleep(1) ,然后看看你是否得到非零结果。
  • 可能和这个问题一样的原因:stackoverflow.com/q/2134363/10077
  • 也许 clock 正在测量 CPU 时间,(如 timesgetrusage)但 CUDA 在 GPU 卡上运行,从内核的角度来看,这是一个外围设备(如打印机)所以大部分时间内核都在等待它。

标签: c++ c linux time cuda


【解决方案1】:

这里有两个问题:

  1. clock() 函数的分辨率太低,无法测量您尝试计时的事件的持续时间
  2. CUDA 内核启动是一个异步操作,因此它几乎不消耗时间(在正常平台上通常为 10-20 微秒)。除非您使用同步 CUDA API 调用来强制主机 CPU 阻塞直到内核完成运行,否则您不会测量执行时间。

CUDA 有自己的高精度计时 API,它是在 GPU 上运行的计时操作的推荐方法。使用它的代码如下所示:

int run_kernel(int array[],int nelements){

    cudaEvent_t start,stop;
    cudaEventCreate(&start);
    cudaEventCreate(&stop);

    cudaEventRecord(start, 0);

    //
    //perform operation on gpu - call sum
    //

    cudaEventRecord(stop, 0); 
    cudaEventSynchronize(stop); 
    float elapsedTime; 
    cudaEventElapsedTime(&elapsedTime, start, stop); 
    printf("time required : %f", elapsed_time); 

    cudaEventDestroy(start);
    cudaEventDestroy(stop);
}

【讨论】:

    【解决方案2】:

    不要使用clock 来计时 CUDA 内核启动。使用cudaEventElapsedTime。即使clock 具有足够高的精度来为您的内核计时(不是),内核启动也是异步的,这意味着控制流在内核完成之前返回到您的调用函数。

    方法如下:

    void run_kernel(...)
    {
      // create "events" which record the start & finish of the kernel of interest
      cudaEvent_t start, end;
      cudaEventCreate(&start);
      cudaEventCreate(&end):
    
      // record the start of the kernel
      cudaEventRecord(start);
    
      // perform operation on gpu - call sum
      sum<<<...>>>(...);
    
      // record the end of the kernel
      cudaEventRecord(end);
    
      // get elapsed time. Note that this call blocks
      // until the kernel is complete
      float ms;
      cudaEventElapsedTime(&ms, start, end);
    
      printf("time required : %f milliseconds", ms);
    
      cudaEventDestroy(start);
      cudaEventDestroy(end);
    }
    

    【讨论】:

      【解决方案3】:

      我相信你现在应该使用clock_gettime()CLOCK_MONOTONIC 来测量经过时间到高分辨率。在我的电脑上分辨率是 1ns,这已经足够了。

      你可以像这样使用它

      #include <time.h>
      ...
      
      struct timespec start, end, res;
      
      clock_getres(CLOCK_MONOTONIC, &res);
      /* exact format string depends on your system, on mine time_t is long */
      printf("Resolution is %ld s, %ld ns\n" res.tv_sec, res.tv_nsec);
      
      clock_gettime(CLOCK_MONOTONIC, &start);
      /* whatever */
      clock_gettime(CLOCK_MONOTONIC, &end);
      

      -lrt编译

      编辑:我看到我在这方面采取了错误的方法,如果你需要的话,显然你应该使用 CUDA 计时。我按照你的问题对系统进行计时。

      【讨论】:

        【解决方案4】:

        cuda 内核启动是异步的,所以必须在内核之后添加 cudaThreadSynchronize()。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-02-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多