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 ...
随机推荐
- c# T4模板生成实体类(sqlserver)
1.用vs新建tt文件. 2.tt文件保存就自动运行 3.tt文件代码如下,设置生成cs文件的命名空间和生成地址 <#@ template language="C#" hos ...
- windows下PostgreSQL 安装与配置
下载地址 https://www.postgresql.org/download/ Download the installer certified by EnterpriseDB for all s ...
- python+selenium+Chrome options参数
python+selenium+Chrome options参数 Chrome Options常用的行为一般有以下几种: 禁止图片和视频的加载:提升网页加载速度. 添加代理:用于翻墙访问某些页面,或者 ...
- Ant Design 表单中getFieldDecorator、getFieldValue、setFieldValue用法
Ant Design 表单中getFieldDecorator.getFieldValue.setFieldValue用法 一.getFieldDecorator getFieldDecorator是 ...
- PHP计算每月几周,每周的开始结束日期
PHP计算每月几周,每周的开始结束日期 因为项目中需要一个每周工作计算的功能,具体日期的算法是,把每月拆分成几个周,最后一个星期这个月份的天数不够就补上下个月的. 列如今天8月27星期一,这个月有31 ...
- 【Spark 内核】 Spark 内核解析-上
Spark内核泛指Spark的核心运行机制,包括Spark核心组件的运行机制.Spark任务调度机制.Spark内存管理机制.Spark核心功能的运行原理等,熟练掌握Spark内核原理,能够帮助我们更 ...
- Yolo V3理解bbox和label的关系
假如一个bbox坐标为:[35 220 62 293 3] 第一步:将bbox转换为中心坐标和宽高形式(3种缩放比例进行缩放) 那么onehot:[0 0 0 1 0 0 0 0 0 0 ...... ...
- python字典的遍历
遍历字典: keys() .values() .items() 1. xxx.keys() : 返回字典的所有的key 返回一个序列,序列中保存有字典的所有的键 效果图: 代码: ...
- 区间dp - codeforces
题意 : 给你 n 个数字,相邻的数字如果相同,则代表他们是一个块的,每次操作可以将一个块的数字变成任意一种数字,求最小操作次数,将整个区间的所有数字变成相同的 思路分析 : 定义 dp[i][j][ ...
- Jquery电子签名制作_jSignature
今天用Jquery的jSignature库制作一个电子签名 后台.net core上传到指定文件夹 下载jquery库 提取码:rd9g html @{ Layout = null; } <!D ...