簡體   English   中英

Nvidia Profiling NVPROF的CPU啟動和GPU啟動的開始和結束的邊界在哪里?

[英]Where is the boundary of start and end of CPU launch and GPU launch of Nvidia Profiling NVPROF?

在CPU和GPU(黃色塊)中內核啟動的開始和結束的定義是什么? 它們之間的界限在哪里?

請注意,CPU和GPU中這些黃色塊的開始,結束和持續時間是不同的。 vecAdd<<<gridSize, blockSize>>>(d_a, d_b, d_c, n); 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黃色塊:

在此處輸入圖片說明

請注意,您提到的是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時間的確切原因,並且它是一個封閉的源庫,因此您需要承認開銷是某種東西您幾乎無法控制。 如果您設計運行時間很長的內核並完成大量工作,那么這些開銷可能就變得微不足道了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM