GPU高性能计算CUDA编程:输出结果和清理

高性能计算CUDA编程:输出结果和清理

声明:本文不做商用

之前的示例代码显示了该如何输出程序的结果。其中一些输出结果来自我们对GPU的查询。例如,GPUprop.name 是GPU的名称,像“GeForce GTX TitanZ”,我将在以后的文章中详细介绍输出。
就像每个 malloc() 调用都必须调用相应的free()函数来释放内存一样,每个 cudaMalloc() 也必须调用cudaFree()来释放,告诉 Nvidia 运行时不再需要该GPU内存区域。同样,使用 cudaEventCreate() 创建的每个事件都必须调用cudaEventDestroy()函数销毁。完成所有这些后,调用 cudaDeviceReset(),它告诉 Nvidia 运行时我们对 GPU 的使用已经结束。然后,我们继续工作,用 fee() 函数释放分配的CPU内存区域,imflipG.cu 运行结束!

int main(int argc, char **argv)
{
    ...
    printf("\n\n--------------------------------------------------------------------------\n");
    printf("%s ComputeCapab=%d.%d [supports max %s blocks; %d thr/blk] \n", 
           GPUprop.name, GPUprop.major, GPUprop.minor, SupportedBlocks, MaxThrPerBlk);
    printf("--------------------------------------------------------------------------\n");
    printf("%s %s %s %c %u   [%u BLOCKS, %u BLOCKS/ROW]\n", ProgName, InputFileName, OutputFileName,
           Flip, ThrPerBlk, NumBlocks, BlkPerRow);
    printf("--------------------------------------------------------------------------\n");
    printf("CPU->GPU Transfer   =%7.2f ms  ...  %4d MB  ...  %6.2f GB/s\n", tfrCPUtoGPU, DATAMB(IMAGESIZE), DATABW(IMAGESIZE, tfrCPUtoGPU));
    printf("Kernel Execution    =%7.2f ms  ...  %4d MB  ...  %6.2f GB/s\n", kernelExecutionTime, DATAMB(GPUDataTransfer), DATABW(GPUDataTransfer, kernelExecutionTime));
    printf("GPU->CPU Transfer   =%7.2f ms  ...  %4d MB  ...  %6.2f GB/s\n", tfrGPUtoCPU, DATAMB(IMAGESIZE), DATABW(IMAGESIZE, tfrGPUtoCPU));
    printf("--------------------------------------------------------------------------\n");
    printf("Total time elapsed  =%7.2f ms       %4d MB  ...  %6.2f GB/s\n", totalTime, DATAMB((2 * IMAGESIZE + GPUDataTransfer)), DATABW((2 * IMAGESIZE + GPUDataTransfer), totalTime));
    printf("--------------------------------------------------------------------------\n\n");

    // Deallocate CPU, GPU memory and destroy events.
    cudaFree(GPUImg);
    cudaFree(GPUCopyImg);
    cudaEventDestroy(time1);
    cudaEventDestroy(time2);
    cudaEventDestroy(time3);
    cudaEventDestroy(time4);
    // cudaDeviceReset must be called before exiting in order for profiling and
    // tracing tools such as Parallel Nsight and Visual Profiler to show complete traces.
    cudaStatus = cudaDeviceReset();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaDeviceReset failed!");
        free(TheImg);
        free(CopyImg);
        exit(EXIT_FAILURE);
    }
    free(TheImg);
    free(CopyImg);
    return(EXIT_SUCCESS);

}

通用的核函数启动代码如下所示:

GPU Kernel Name <<< dimension,dimension >>> (arg1,arg2,...);

其中argl、arg2、……是从CPU端传递到GPU核函数的参数。参见【0voice C++】在代码6.3中,它们是两个指针和IPH。在GPU内存区域创建存储图像存储空间时,由两个指针(GPUCopyImg和GPUImg)cudaMalloc()返回。IPH是一个变量,存放图像水平方向上的像素数(ipHpixels)。GPU的核函数Hfip()在执行期间需要这三个参数,如果在核函数启动时没有被传递进来,核函数将无法获得它们。回忆一下,类比6.2中的两个维度分别是166656和256,实际上对应于下面的启动代码:

Hflip <<< 166,656,256 >>> (GPUCopyImg,GPUImg, IPH);

这告诉Nvidia运行时引擎为Hflip()核函数启动166656个线程块,并将这三个参数传递给每一个线程块。也就是启动:线程块0、线程块1、线程块2、……、线程块166655。每一…、tid=255),与我们在本书第一部分中个线程块都将启动256个线程(tid=0、tid=1、看到的 pthread示例相同。我们真正想说的是,该行代码总共启动了166656x256~41M个线程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值