1

CPU 和 GPU(黄色块)中内核启动的开始和结束的定义是什么?他们之间的界限在哪里?

请注意CPU和GPU中那些黄色块的开始,结束和持续时间是不同的。为什么CPU调用vecAdd<<<gridSize, blockSize>>>(d_a, d_b, d_c, n);需要那么长时间?

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// CUDA kernel. Each thread takes care of one element of c
__global__ void vecAdd(double *a, double *b, double *c, int n)
{
    // Get our global thread ID
    int id = blockIdx.x*blockDim.x+threadIdx.x;
    //printf("id = %d \n", id);

    // Make sure we do not go out of bounds
    if (id < n)
        c[id] = a[id] + b[id];
}

int main( int argc, char* argv[] )
{
    // Size of vectors
    int n = 1000000;

    // Host input vectors
    double *h_a;
    double *h_b;
    //Host output vector
    double *h_c;

    // Device input vectors
    double *d_a;
    double *d_b;
    //Device output vector
    double *d_c;

    // Size, in bytes, of each vector
    size_t bytes = n*sizeof(double);

    // Allocate memory for each vector on host
    h_a = (double*)malloc(bytes);
    h_b = (double*)malloc(bytes);
    h_c = (double*)malloc(bytes);

    // Allocate memory for each vector on GPU
    cudaMalloc(&d_a, bytes);
    cudaMalloc(&d_b, bytes);
    cudaMalloc(&d_c, bytes);

    int i;
    // Initialize vectors on host
    for( i = 0; i < n; i++ ) {
        h_a[i] = sin(i)*sin(i);
        h_b[i] = cos(i)*cos(i);
    }

    // Copy host vectors to device
    cudaMemcpy( d_a, h_a, bytes, cudaMemcpyHostToDevice);
    cudaMemcpy( d_b, h_b, bytes, cudaMemcpyHostToDevice);

    int blockSize, gridSize;

    // Number of threads in each thread block
    blockSize = 1024;

    // Number of thread blocks in grid
    gridSize = (int)ceil((float)n/blockSize);

    // Execute the kernel
    vecAdd<<<gridSize, blockSize>>>(d_a, d_b, d_c, n);

    // Copy array back to host
    cudaMemcpy( h_c, d_c, bytes, cudaMemcpyDeviceToHost );

    // Sum up vector c and print result divided by n, this should equal 1 within error
    double sum = 0;
    for(i=0; i<n; i++)
        sum += h_c[i];
    printf("final result: %f\n", sum/n);

    // Release device memory
    cudaFree(d_a);
    cudaFree(d_b);
    cudaFree(d_c);

    // Release host memory
    free(h_a);
    free(h_b);
    free(h_c);

    return 0;
}

CPU黄块:

在此处输入图像描述

GPU黄块:

在此处输入图像描述

4

1 回答 1

2

请注意,您提到了 NVPROF,但您显示的图片来自 nvvp - 视觉分析器。nvprof 是命令行分析器

GPU 内核启动是异步的。这意味着 CPU 线程启动内核但不等待内核完成。事实上,CPU 活动实际上是将内核置于启动队列中——如果 GPU 上发生其他任何事情,内核的实际执行可能会延迟。

因此,CPU (API) 活动和 GPU 活动之间没有明确的关系,只是 CPU 内核启动必须明显(至少稍微)先于 GPU 内核执行。

CPU (API) 黄色块代表 CPU 线程在库调用到 CUDA 运行时库中花费的时间,以启动内核(即,将其放入启动队列)。这个库调用活动通常有一些与之相关的时间开销,在 5-50 微秒的范围内。这段时间的开始以调用库的开始为标志。这段时间的结束由库将控制权返回给您的代码(即内核启动后的下一行代码)的时间标记。

GPU 黄色块代表内核在 GPU 上执行的实际时间段。这个黄色块的开始和结束由 GPU 上内核活动的开始和结束标记。这里的持续时间是内核中的代码正在做什么以及需要多长时间的函数。

我不认为 GPU 内核启动需要大约 5-50 微秒的 CPU 时间的确切原因在任何地方都没有以权威的方式记录或解释,而且它是一个封闭源代码库,因此您需要承认这种开销是什么你几乎无法控制。如果您设计的内核可以运行很长时间并进行大量工作,那么这种开销可能会变得微不足道。

于 2019-05-14T23:11:30.810 回答