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

相关文章

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-

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

【经验交流】修复系统事件查看器启动不能时出现的4201错误

方法1,取得『%SystemRoot%\LogFiles』文件夹和『%SystemRoot%\System32\wbem』文件夹的权限(包括这两个文件夹的所有子文件夹的权限),简单点说,就是使你当前的帐户拥有这两个文件夹以及它们的子文件夹的绝对控制权限。这是最简单的方法,不少老外说,这样一弄,倒是解决了问题。不过对我的系统,没用; 方法2,以不带网络的安全模式启动,运行命令行,输入“ne

BT天堂网站挂马事件后续:“大灰狼”远控木马分析及幕后真凶调查

9月初安全团队披露bt天堂网站挂马事件,该网站被利用IE神洞CVE-2014-6332挂马,如果用户没有打补丁或开启安全软件防护,电脑会自动下载执行大灰狼远控木马程序。 鉴于bt天堂电影下载网站访问量巨大,此次挂马事件受害者甚众,安全团队专门针对该木马进行严密监控,并对其幕后真凶进行了深入调查。 一、“大灰狼”的伪装 以下是10月30日一天内大灰狼远控的木马样本截图,可以看到该木马变种数量不

GPU 计算 CMPS224 2021 学习笔记 02

并行类型 (1)任务并行 (2)数据并行 CPU & GPU CPU和GPU拥有相互独立的内存空间,需要在两者之间相互传输数据。 (1)分配GPU内存 (2)将CPU上的数据复制到GPU上 (3)在GPU上对数据进行计算操作 (4)将计算结果从GPU复制到CPU上 (5)释放GPU内存 CUDA内存管理API (1)分配内存 cudaErro