CUDA学习(七)之使用CUDA内置API计时
问题:对于使用GPU计算时,都想知道kernel函数运行所耗费的时间,使用CUDA内置的API可以方便准确的获得kernel运行时间。
在CPU上,可以使用clock()函数和GetTickCount()函数计时。
clock_t start, end;
start = clock();
//执行步骤;
......
end = clock();
printf(" time (CPU) : %f ms(毫秒) \n", end - start);
int startTime, endTime;
// 开始时间
startTime = GetTickCount();
//执行步骤;
......
endTime = GetTickCount();
cout << " 总时间为 : " << (double)(endTime - startTime)<< " ms " << endl;
对于CUDA核函数计时使用clock()或GetTickCount()函数结果不准确,计算归约求和的例子如下:
//CPU计时
clock_t start, end;
start = clock(); d_SharedMemoryTest << < NThreadX, ThreadX >> > (S_Para, MX); //调用核函数(M个包含N个线程的线程块) cudaDeviceSynchronize();
end = clock(); clock_t time = end - start;
printf(" time (GPU) : %f ms \n", time);
结果为0.000000 ms(明显结果错误):

而使用CUDA内置API(cudaEvent_t)计时,主要代码如下
//GPU计时
cudaEvent_t startTime, endTime;
cudaEventCreate(&startTime);
cudaEventCreate(&endTime);
cudaEventRecord(startTime, ); d_SharedMemoryTest << < NThreadX, ThreadX >> > (S_Para, MX); //调用核函数(M个包含N个线程的线程块) cudaEventRecord(endTime, );
cudaEventSynchronize(startTime);
cudaEventSynchronize(endTime); float time;
cudaEventElapsedTime(&time, startTime, endTime);
printf(" time (GPU) : %f ms \n", time); cudaEventDestroy(startTime);
cudaEventDestroy(endTime);
结果为39.848801 ms:

最后附上全部代码:
#pragma once
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "device_functions.h" #include <iostream> using namespace std;
const int NX = ; //数组长度
const int ThreadX = ; //线程块大小 //使用shared memory和多个线程块
__global__ void d_SharedMemoryTest(double *para, int MX)
{
int i = threadIdx.x; //该线程块中线程索引
int tid = blockIdx.x * blockDim.x + threadIdx.x; //M个包含N个线程的线程块中相对应全局内存数组的索引(全局线程) __shared__ double s_Para[ThreadX]; //定义固定长度(线程块长度)的共享内存数组
if (tid < MX) //判断全局线程小于整个数组长度NX,防止数组越界
s_Para[i] = para[tid]; //将对应全局内存数组中一段元素的值赋给共享内存数组
__syncthreads(); //(红色下波浪线提示由于VS不识别,不影响运行)同步,等待所有线程把自己负责的元素载入到共享内存再执行下面代码 if (tid < MX)
{
for (int index = ; index < blockDim.x; index *= ) //归约求和 (对应256=4*4*4*4线程数)
{
__syncthreads();
if (i % ( * index) == )
{
s_Para[i] += s_Para[i + index] + s_Para[i + *index] + s_Para[i + *index];
}
}
} if (i == ) //求和完成,总和保存在共享内存数组的0号元素中
para[blockIdx.x * blockDim.x + i] = s_Para[i]; //在每个线程块中,将共享内存数组的0号元素赋给全局内存数组的对应元素,即线程块索引*线程块维度+i(blockIdx.x * blockDim.x + i) } //使用shared memory和多个线程块
void s_ParallelTest()
{
double *Para;
cudaMallocManaged((void **)&Para, sizeof(double) * NX); //统一内存寻址,CPU和GPU都可以使用 double ParaSum = ;
for (int i = ; i<NX; i++)
{
Para[i] = ; //数组赋值
ParaSum += Para[i]; //CPU端数组累加
} cout << " CPU result = " << ParaSum << endl; //显示CPU端结果
double d_ParaSum; int Blocks = ((NX + ThreadX - ) / ThreadX);
cout << " 线程块大小 :" << ThreadX << " 线程块数量 :" << Blocks << endl; double *S_Para;
int MX = ThreadX * Blocks;
cudaMallocManaged(&S_Para, sizeof(double) * MX);
for (int i=; i<MX; i++)
{
if (i < NX)
S_Para[i] = Para[i];
} ////CPU计时
//clock_t start, end;
//start = clock(); //d_SharedMemoryTest << < Blocks, ThreadX >> > (S_Para, MX); //调用核函数(M个包含N个线程的线程块)
//
//cudaDeviceSynchronize();
//end = clock(); //clock_t time = end - start;
//printf(" time (GPU) : %f ms \n", time); //GPU计时
cudaEvent_t startTime, endTime;
cudaEventCreate(&startTime);
cudaEventCreate(&endTime);
cudaEventRecord(startTime, ); d_SharedMemoryTest << < Blocks, ThreadX >> > (S_Para, MX); //调用核函数(M个包含N个线程的线程块) cudaEventRecord(endTime, );
cudaEventSynchronize(startTime);
cudaEventSynchronize(endTime); float time;
cudaEventElapsedTime(&time, startTime, endTime);
printf(" time (GPU) : %f ms \n", time); cudaEventDestroy(startTime);
cudaEventDestroy(endTime); for (int i=; i<Blocks; i++)
{
d_ParaSum += S_Para[i*ThreadX]; //将每个线程块相加求的和(保存在对应全局内存数组中)相加求和
} cout << " GPU result = " << d_ParaSum << endl; //显示GPU端结果 } int main() { s_ParallelTest(); system("pause");
return ;
}
CUDA学习(七)之使用CUDA内置API计时的更多相关文章
- Python基础学习参考(三):内置函数
一:内置函数 在第一篇文章中,我们简单的认识了一下print()函数和input()函数,也就是输入和输出,这些函数我们可以直接的调用,不要自己定义或者引入什么,对吧?想这样的函数就叫做内置函数.这里 ...
- 前端MVC学习总结(三)——AngularJS服务、路由、内置API、jQueryLite
一.服务 AngularJS功能最基本的组件之一是服务(Service).服务为你的应用提供基于任务的功能.服务可以被视为重复使用的执行一个或多个相关任务的代码块. AngularJS服务是单例对象, ...
- 前端MVC学习笔记(三)——AngularJS服务、路由、内置API、jQueryLite
一.服务 AngularJS功能最基本的组件之一是服务(Service).服务为你的应用提供基于任务的功能.服务可以被视为重复使用的执行一个或多个相关任务的代码块. AngularJS服务是单例对象, ...
- 学习angularjs的内置API函数
angularjs的内置API函数有很多,如isString()判断给定的对象是否为字符串,如果是返回 true,反之返回false:isNumber()判断给定的对象是否为数字,如果是返回 true ...
- ruby -- 基础学习(七)时间的内置函数和格式说明
Rails -- 时间的内置函数和格式说明 FROM:http://www.douban.com/note/99064603/ time = Time.now #获得当前时间 time.gmt ...
- Python基础学习笔记(七)常用元组内置函数
参考资料: 1. <Python基础教程> 2. http://www.runoob.com/python/python-tuples.html 3. http://www.liaoxue ...
- Python学习day07 - Python进阶(1) 内置方法
figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...
- AngularJS学习笔记(四)内置指令
说说指令 不得不赞叹,指令是ng最为强大的功能之一,好吧,也可以去掉之一,是最强大的功能.ng内置了许多自定义的指令,这避免了我们自己去造轮子.同时,ng也提供了自定义指令的功能,可以让我们的页面元素 ...
- Python学习(五)函数 —— 内置函数 lambda filter map reduce
Python 内置函数 lambda.filter.map.reduce Python 内置了一些比较特殊且实用的函数,使用这些能使你的代码简洁而易读. 下面对 Python 的 lambda.fil ...
随机推荐
- $loj526\ [LibreOJ\ \beta\ Round\ \#4]$ 子集 图论
正解:图论 解题报告: 传送门$QwQ$ 发现最大团不好求,于是考虑求最大独立集.也就把所有$gcd(i,j)\cdot gcd(i+1,j+1)=1$的点之间连边,然后求最大独立集. 发现依然不可做 ...
- 三分钟学会使用Docker部署.NET Core
大概快有一年的时间没有碰过docker了,理由很简单,基本上都是在IIS上部署,看到很多大佬都开始Devops持续化集成了,但相对来说成本会更高,但对于大型团队来说还是不错的,这不?不想被大伙甩下,哈 ...
- requests-html库render方法的使用
一.render的使用 from requests_html import HTMLSession session =HTMLSession() response = session.get('htt ...
- Java和JavaScript之间的区别
1.简介 通过优锐课核心java学习笔记中,我们可以看到,Java和JavaScript之间的区别.我们将在本文中比较Java语言和JavaScript语言.JavaScript由Netscape开发 ...
- 小白学 Python 爬虫(36):爬虫框架 Scrapy 入门基础(四) Downloader Middleware
人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...
- 让vue-router渲染为指定的标签
<router-link :to="{name:'cart'}" tag="li"> cart </router-link> 在rout ...
- 序列积第m小元素 二分答案优化
给出两个长度为n的数组A和B, 在A和B中各任取一个, 可以得到n×n个积. 求第m小的元素. n<=100000 这一道题的意思就是 a1 a2 a3 a4.. b1 b2 b3 b4 n^2 ...
- 一文搞定Spring Boot + Vue 项目在Linux Mysql环境的部署(强烈建议收藏)
本文介绍Spring Boot.Vue .Vue Element编写的项目,在Linux下的部署,系统采用Mysql数据库.按照本文进行项目部署,不迷路. 1. 前言 典型的软件开发,经过" ...
- 跟着知识追寻者学BeautifulSoup,你学不会打不还口,骂不还手
一 前言 Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库:其强大的提取能力让知识追寻者放弃了使用正则匹配查找HTML节点:Beautifu Soup 其能直接 ...
- 【ARM】---STM32位带操作总结---浅显易懂
正在准备做毕业设计,配置LED_Config()的时候,又看到了位带操作的宏定义,我又嘀咕了,什么是位带操作,一年前在使用位带操作的时候,就查阅过好多资料,Core-M3也看过,但是对于博主这种“低能 ...