GPU(七)CUDA事件计时与nvprof

2024-04-01 04:04
文章标签 事件 gpu cuda 计时 nvprof

本文主要是介绍GPU(七)CUDA事件计时与nvprof,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CUDA runtime API文档参考:https://docs.nvidia.com/cuda/pdf/CUDA_Runtime_API.pdf

1、CUDA事件计时

不管是CPU程序,还是CUDA GPU程序,性能永远是一个重要的关注点,而评估一段程序的性能,耗时是一个非常直观的指标。假设我们要测试某个函数的耗时,一般会在该函数开始时计时一下,函数结束的时候计时一下,最终计算两个时间差。在普通程序中完全可以这么做,但是在CUDA GPU程序的host和device具有异构计算特性,如果把计时代码放在CPU处执行,则在第二次计时前,要做好同步操作。本章节讨论一种CUDA事件计时(也就是在device上计时的方式)来计算核函数执行时间的方法。

1.1 事件计时CUDA函数

本章节要用到的CUDA函数定义和功能如下:

  • cudaEventCreate

函数定义:__host__cudaError_t cudaEventCreate (cudaEvent_t *event)

函数功能:创建一个事件对象

  • cudaEventRecord

函数定义:__host____device__cudaError_t cudaEventRecord(cudaEvent_t event, cudaStream_t stream)

函数功能:记录一个事件

  • cudaEventQuery

函数定义:__host__cudaError_t cudaEventQuery (cudaEvent_t event)

函数功能:查询一个事件状态

  • cudaEventSynchronize

函数定义:__host__cudaError_t cudaEventSynchronize(cudaEvent_t event)

函数功能:等待一个事件完成

  • cudaEventElapsedTime

函数定义: __host__cudaError_t cudaEventElapsedTime (float *ms, cudaEvent_t start, cudaEvent_t end)

函数功能:计算两个事件的运行时间差

  • cudaEventDestroy

函数定义:__host____device__cudaError_t cudaEventDestroy(cudaEvent_t event)

函数功能:销毁一个事件对象

1.2 事件计时示例函数

基于上面的CUDA函数,我们写一个简单的CUDA程序:

// time.cu
#include<stdio.h>
#include<stdlib.h>
#include<time.h>const int g_buffer_size = 1024; // 数组大小
const int g_buffer_bytes = g_buffer_size*sizeof(float);
const int calc_count = 1000*1000; // 100w次计算
const long s2ns = 1000000000;
const long ms2ns = 1000000;void init_data(float *p_host){for (int i = 0; i < g_buffer_size; i++){p_host[i] = float(rand() % g_buffer_size);}
}__global__ void device_calc(float *p_device){const int idx = threadIdx.x + blockIdx.x*blockDim.x;p_device[idx] *= 1;
}void host_calc(float * p_host){for (int i = 0; i < g_buffer_size; i++){p_host[i] *= 1;}
}void host_time(float *p_host){struct timespec start, end;clock_gettime(CLOCK_REALTIME, &start);for (int i = 0; i < calc_count; i++){host_calc(p_host);}clock_gettime(CLOCK_REALTIME, &end);long start_us = start.tv_sec*s2ns+start.tv_nsec;long end_us = end.tv_sec*s2ns+end.tv_nsec;printf("host_time diff: %ld ms\n", (end_us-start_us)/ms2ns);
}void device_time(float *p_device){cudaEvent_t start, stop;cudaEventCreate(&start);cudaEventCreate(&stop);cudaEventRecord(start);cudaEventQuery(start);for (int i = 0; i < calc_count; i++){device_calc<<<1, g_buffer_size>>>(p_device);}cudaEventRecord(stop);cudaEventSynchronize(stop);float elapsed_time;cudaEventElapsedTime(&elapsed_time, start, stop);printf("device_time: %g ms\n", elapsed_time);cudaEventDestroy(start);cudaEventDestroy(stop);
}int main(){// host数组初始化float *p_host = (float*)malloc(g_buffer_bytes);if (p_host == NULL) {printf("malloc failed");exit(-1);}memset(p_host, 0, g_buffer_bytes);// 初始化host数据init_data(p_host);// device数组初始化float *p_device;cudaMalloc((float**)&p_device, g_buffer_bytes);if (p_device == NULL) {printf("cudaMalloc failed");free(p_host);exit(-1);}cudaMemset(p_device, 0, g_buffer_bytes);// 拷贝host数据到devicecudaMemcpy(p_device, p_host, g_buffer_bytes, cudaMemcpyHostToDevice);// host上计算时间host_time(p_host);// device上计算时间device_time(p_device);// 释放内存free(p_host);cudaFree(p_device);return 0;
}

在上面的CUDA程序中,我们分别用CPU和GPU对一个长度为1024的float数组做了100W次简单计算,然后计算耗时,注意在GPU计算的计时处,我们用的是CUDA事件计时方法。编译运行:

$ nvcc time.cu -o time
$ ./time
host_time diff: 997 ms
device_time: 6058.68 ms

从运行结果来看,CPU比GPU快很多,这是因为CPU单核运算速度比GPU单核更快,以及数据通过PCIe从host到device比较耗时等原因,在处理少量数据时会更有优势。但是如果把数据量和计算复杂度提上来,GPU就有更大的发挥空间了。

2、nvprof

除了像上面那样显示的在程序中加入计时来分析程序的性能,NVIDIA还提供了一个叫做nvprof的工具,我们把上面的代码稍微修改一下来看看nvprof工具的用法:

// nvprof.cu
#include<stdio.h>
#include<stdlib.h>
#include<time.h>const int g_buffer_size = 1024; // 数组大小
const int g_buffer_bytes = g_buffer_size*sizeof(float);void init_data(float *p_host){for (int i = 0; i < g_buffer_size; i++){p_host[i] = float(rand() % g_buffer_size);}
}__global__ void device_calc(float *p_device){const int idx = threadIdx.x + blockIdx.x*blockDim.x;p_device[idx] *= 1;
}int main(){// host数组初始化float *p_host = (float*)malloc(g_buffer_bytes);if (p_host == NULL) {printf("malloc failed");exit(-1);}memset(p_host, 0, g_buffer_bytes);// 初始化host数据init_data(p_host);// device数组初始化float *p_device;cudaMalloc((float**)&p_device, g_buffer_bytes);if (p_device == NULL) {printf("cudaMalloc failed");free(p_host);exit(-1);}cudaMemset(p_device, 0, g_buffer_bytes);// 拷贝host数据到devicecudaMemcpy(p_device, p_host, g_buffer_bytes, cudaMemcpyHostToDevice);device_calc<<<1, g_buffer_size>>>(p_device);// 释放内存free(p_host);cudaFree(p_device);return 0;
}

编译CUDA程序生成可执行文件:

$ nvcc nvprof.cu -o prof
$ ll prof
-rwxr-xr-x 1 nuczzz nuczzz 989504 Mar 31 21:48 prof*

执行nsys nvprof ./prof得到如下结果,可以看出这段程序主要耗时是在cudaMalloc

在一些低版本中,可以直接使用nvprof ./prof,高版本需要加上nsys

$ nsys nvprof ./prof
WARNING: prof and any of its children processes will be profiled.Generating '/tmp/nsys-report-795c.qdstrm'
[1/7] [========================100%] report1.nsys-rep
[2/7] [========================100%] report1.sqlite
[3/7] Executing 'nvtx_sum' stats report
SKIPPED: /home/nuczzz/c/day4/report1.sqlite does not contain NV Tools Extension (NVTX) data.
[4/7] Executing 'cuda_api_sum' stats reportTime (%)  Total Time (ns)  Num Calls   Avg (ns)     Med (ns)    Min (ns)   Max (ns)   StdDev (ns)           Name--------  ---------------  ---------  -----------  -----------  ---------  ---------  -----------  ----------------------99.8        180894728          1  180894728.0  180894728.0  180894728  180894728          0.0  cudaMalloc0.1           175601          1     175601.0     175601.0     175601     175601          0.0  cudaFree0.1           120538          1     120538.0     120538.0     120538     120538          0.0  cudaLaunchKernel0.0            62816          1      62816.0      62816.0      62816      62816          0.0  cudaMemcpy0.0            12792          1      12792.0      12792.0      12792      12792          0.0  cudaMemset0.0              804          1        804.0        804.0        804        804          0.0  cuModuleGetLoadingMode[5/7] Executing 'cuda_gpu_kern_sum' stats report
SKIPPED: /home/nuczzz/c/day4/report1.sqlite does not contain CUDA kernel data.
[6/7] Executing 'cuda_gpu_mem_time_sum' stats report
SKIPPED: /home/nuczzz/c/day4/report1.sqlite does not contain GPU memory data.
[7/7] Executing 'cuda_gpu_mem_size_sum' stats report
SKIPPED: /home/nuczzz/c/day4/report1.sqlite does not contain GPU memory data.
Generated:/home/nuczzz/c/day4/report1.nsys-rep/home/nuczzz/c/day4/report1.sqlite

微信公众号卡巴斯同步发布,欢迎大家关注。

这篇关于GPU(七)CUDA事件计时与nvprof的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/866155

相关文章

conda安装GPU版pytorch默认却是cpu版本

《conda安装GPU版pytorch默认却是cpu版本》本文主要介绍了遇到Conda安装PyTorchGPU版本却默认安装CPU的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目录一、问题描述二、网上解决方案罗列【此节为反面方案罗列!!!】三、发现的根本原因[独家]3.1 p

Python使用Turtle实现精确计时工具

《Python使用Turtle实现精确计时工具》这篇文章主要为大家详细介绍了Python如何使用Turtle实现精确计时工具,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下... 目录功能特点使用方法程序架构设计代码详解窗口和画笔创建时间和状态显示更新计时器控制逻辑计时器重置功能事件

Python开发文字版随机事件游戏的项目实例

《Python开发文字版随机事件游戏的项目实例》随机事件游戏是一种通过生成不可预测的事件来增强游戏体验的类型,在这篇博文中,我们将使用Python开发一款文字版随机事件游戏,通过这个项目,读者不仅能够... 目录项目概述2.1 游戏概念2.2 游戏特色2.3 目标玩家群体技术选择与环境准备3.1 开发环境3

判断PyTorch是GPU版还是CPU版的方法小结

《判断PyTorch是GPU版还是CPU版的方法小结》PyTorch作为当前最流行的深度学习框架之一,支持在CPU和GPU(NVIDIACUDA)上运行,所以对于深度学习开发者来说,正确识别PyTor... 目录前言为什么需要区分GPU和CPU版本?性能差异硬件要求如何检查PyTorch版本?方法1:使用命

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,

spring @EventListener 事件与监听的示例详解

《spring@EventListener事件与监听的示例详解》本文介绍了自定义Spring事件和监听器的方法,包括如何发布事件、监听事件以及如何处理异步事件,通过示例代码和日志,展示了事件的顺序... 目录1、自定义Application Event2、自定义监听3、测试4、源代码5、其他5.1 顺序执行

Python中的异步:async 和 await以及操作中的事件循环、回调和异常

《Python中的异步:async和await以及操作中的事件循环、回调和异常》在现代编程中,异步操作在处理I/O密集型任务时,可以显著提高程序的性能和响应速度,Python提供了asyn... 目录引言什么是异步操作?python 中的异步编程基础async 和 await 关键字asyncio 模块理论

禁止平板,iPad长按弹出默认菜单事件

通过监控按下抬起时间差来禁止弹出事件,把以下代码写在要禁止的页面的页面加载事件里面即可     var date;document.addEventListener('touchstart', event => {date = new Date().getTime();});document.addEventListener('touchend', event => {if (new

AI Toolkit + H100 GPU,一小时内微调最新热门文生图模型 FLUX

上个月,FLUX 席卷了互联网,这并非没有原因。他们声称优于 DALLE 3、Ideogram 和 Stable Diffusion 3 等模型,而这一点已被证明是有依据的。随着越来越多的流行图像生成工具(如 Stable Diffusion Web UI Forge 和 ComyUI)开始支持这些模型,FLUX 在 Stable Diffusion 领域的扩展将会持续下去。 自 FLU

如何用GPU算力卡P100玩黑神话悟空?

精力有限,只记录关键信息,希望未来能够有助于其他人。 文章目录 综述背景评估游戏性能需求显卡需求CPU和内存系统需求主机需求显式需求 实操硬件安装安装操作系统Win11安装驱动修改注册表选择程序使用什么GPU 安装黑神话悟空其他 综述 用P100 + PCIe Gen3.0 + Dell720服务器(32C64G),运行黑神话悟空画质中等流畅运行。 背景 假设有一张P100-