2

我试图正确测量并行和顺序执行的时间,但我有疑问,因为:

假设我们有以下代码:

    //get the time
    clock_t start,finish;
    double totaltime;
    start = clock(); 

    double *d_A, *d_B, *d_X;

    cudaMalloc((void**)&d_A, sizeof(double) * Width * Width);
    cudaMalloc((void**)&d_B, sizeof(double) * Width);
    cudaMalloc((void**)&d_X, sizeof(double) * Width);

    cudaMemcpy(d_A, A, sizeof(double) * Width * Width, cudaMemcpyHostToDevice);
    cudaMemcpy(d_B, B, sizeof(double) * Width, cudaMemcpyHostToDevice);  


    do_parallel_matmul<<<dimB, dimT>>>(d_A, d_B, d_X, Width);   
    

    cudaMemcpy(X, d_X, sizeof(double) * Width, cudaMemcpyDeviceToHost);

    finish = clock();
    
    totaltime=(double)(finish-start)/CLOCKS_PER_SEC;   

    printf("%f", totaltime);

这个时间比连续时间长得多,测量如下:

clock_t start,finish;
double totaltime;
start = clock(); 

do_seq_matmult();

finish = clock();
    
totaltime=(double)(finish-start)/CLOCKS_PER_SEC;   

printf("%f", totaltime);

所以我不知道我是否应该只测量CUDA内核时间如下:

clock_t start,finish;
double totaltime;
start = clock(); 

do_parallel_matmul();

finish = clock();
    
totaltime=(double)(finish-start)/CLOCKS_PER_SEC;   

printf("%f", totaltime);

并避免主机和设备之间的内存复制......

我之所以问上述问题,是因为我必须提交并行执行和顺序执行之间的比较...但是如果我在 CUDA 中测量内存副本,那么 CUDA 和 C 之间并没有很大的区别...

编辑:

void do_seq_matmult(const double *A, const double *X, double *resul, const int tam)
{
    *resul = 0;
    for(int i = 0; i < tam; i++)
    {
        for(int  j = 0; j < tam; j++)
        {
            if(i != j)
                *resul += A[i * tam + j] * X[j];
        }
    }
}

__global__ void do_parallel_matmul( double * mat_A, 
                            double * vec, 
                            double * rst, 
                            int dim)
{
     int rowIdx = threadIdx.x + blockIdx.x * blockDim.x; // Get the row Index 
     int aIdx;
     while( rowIdx < dim)
     {
          rst[rowIdx] = 0; // clean the value at first
          for (int i = 0; i < dim; i++)
          {
               aIdx = rowIdx * dim + i; // Get the index for the element a_{rowIdx, i}
               rst[rowIdx] += (mat_A[aIdx] * vec[i] ); // do the multiplication
          }
          rowIdx += gridDim.x * blockDim.x;
     }
     __syncthreads();
}
4

3 回答 3

2

您在测量中使用了错误的功能。clock测量您的进程在 CPU 上花费的时间,而不是挂钟时间。

于 2012-08-15T14:47:52.830 回答
1

看看High Precision Timer库,它使用 OS 相关的计时功能来测量时间。

它使用了一组可以为您提供微秒精度的函数。

如果你在 Windows 上,你应该 在 Linux 上使用QueryPerformanceFrequency和:QueryPerformanceCountergettimeofday()

它非常轻便且易于使用。适用于 Windows 和 Linux。

于 2012-08-15T14:53:57.047 回答
0

一些想法:

  1. 在没有主机分配内存的情况下,将设备内存分配的时间与 CPU 进行比较是不公平的。

  2. 如果 cudaMalloc((void**)&d_A, sizeof(double) * Width * Width); 是第一个 CUDA 调用,它将包括 CUDA 上下文创建,这可能是一个很大的开销。

  3. 计时 cudamemcpy 不是一个公平的 CPU/GPU 比较,因为这个时间将取决于系统的 PCI-e 带宽。另一方面,如果您从 CPU 的角度将内核视为加速,则需要包含 memcpy。为了使 PCI-e 带宽达到峰值,请使用页面锁定内存。

  4. 如果您的应用程序要多次运行乘法运算,那么您可以通过将副本与内核执行重叠来隐藏大部分 memcpy。这在你有双 DMA 引擎的特斯拉单元上更好。

  5. 为内核本身计时将要求您在停止计时器之前将 CPU 与 GPU 同步,否则您将只为内核启动本身而不是执行计时。从 CPU 调用内核是异步的。如果您想为 GPU 上的内核执行计时,请使用 cudaEvents。

  6. 在 GPU 上运行多个线程以获得公平的比较。

  7. 改进内核,你可以做得更好。

于 2012-08-15T14:52:54.730 回答