CUDA 事件计时

news2024/10/21 3:10:52

CUDA 事件 可以为主机代码和设备代码计时。

基本的语法

// 定义事件变量
cudaEvent_t start, stop;
// 初始化
cudaEventCreate(&start);
cudaEventCreate(&stop);
// 记录代表时间开始的事件,注意不是地址
cudaEventRecord(start);
// 在TCC的驱动下可以省略,在WDDM驱动模式下必须保留,所以默认保留
// 不可以使用错误检测函数,默认返回值是错误的
cudaEventQuery(start);


/**
* code
**/

// 记录代表时间结束的事件
cudaEventRecord(stop);
// 事件同步函数,等待事件记录结束
cudaEventSynchronize(stop);
// 计算时间差
float elapsed_time;
cudaEventElapsedTime(&elapsed_time, start, stop);

// 销毁变量
cudaEventDestroy(start);
cudaEventDestroy(stop);

使用示例:

计算两个数组的和

#include <cuda_runtime.h>
#include <device_launch_parameters.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

#define NUM_REPEATS 10

static void CheckCudaErrorAux(const char*, unsigned, const char*, cudaError_t);
#define CUDA_CHECK_RETURN(value) CheckCudaErrorAux(__FILE__,__LINE__, #value, value)


// 设备函数
__device__ float add(const float x, const float y)
{
	return x + y;
}

__global__ void addFromGPU(float* A, float* B, float* C, const int N)
{
	int blockId = blockIdx.x;
	int id = blockId * blockDim.x + threadIdx.x;
	if (id >= N)
	{
		return;
	}

	C[id] = add(A[id], B[id]);
}

void initialData(float* addr, int nCount)
{
	for (size_t i = 0; i < nCount; i++)
	{
		addr[i] = (float)(rand() & 0xFFF) / 100.f;
	}
}

int main()
{
	int iElemntCount = 4096*10;
	size_t stBytesCount = iElemntCount * sizeof(float); // 字节数

	// 分配主机内存和设备内存并初始化
	float* fpHost_A = new float[iElemntCount];
	float* fpHost_B = new float[iElemntCount];
	float* fpHost_C = new float[iElemntCount];
	memset(fpHost_A, 0, stBytesCount);
	memset(fpHost_B, 0, stBytesCount);
	memset(fpHost_C, 0, stBytesCount);
	float* fpDevice_A, * fpDevice_B, * fpDevice_C;
	CUDA_CHECK_RETURN(cudaMalloc((void**)&fpDevice_A, stBytesCount));
	CUDA_CHECK_RETURN(cudaMalloc((void**)&fpDevice_B, stBytesCount));
	CUDA_CHECK_RETURN(cudaMalloc((void**)&fpDevice_C, stBytesCount));

	CUDA_CHECK_RETURN(cudaMemset(fpDevice_C, 0,stBytesCount));

	srand(666);
	initialData(fpHost_A, iElemntCount);
	initialData(fpHost_B, iElemntCount);

	CUDA_CHECK_RETURN(cudaMemcpy(fpDevice_A, fpHost_A, stBytesCount, cudaMemcpyHostToDevice));
	CUDA_CHECK_RETURN(cudaMemcpy(fpDevice_B, fpHost_B, stBytesCount, cudaMemcpyHostToDevice));


	dim3 block(32);
	dim3 grid((iElemntCount + block.x - 1)/ block.x);

	cudaEvent_t start, stop;

	for (int i = 0; i < NUM_REPEATS; i++)
	{
		CUDA_CHECK_RETURN(cudaEventCreate(&start));
		CUDA_CHECK_RETURN(cudaEventCreate(&stop));
		CUDA_CHECK_RETURN(cudaEventRecord(start));
		cudaEventQuery(start);

		addFromGPU <<<grid, block >>> (fpDevice_A, fpDevice_B, fpDevice_C, iElemntCount);

		CUDA_CHECK_RETURN(cudaEventRecord(stop));
		CUDA_CHECK_RETURN(cudaEventSynchronize(stop));
		float elapsed_time = 0.0f;
		CUDA_CHECK_RETURN(cudaEventElapsedTime(&elapsed_time, start, stop));
		CUDA_CHECK_RETURN(cudaEventDestroy(start));
		CUDA_CHECK_RETURN(cudaEventDestroy(stop));

		printf("%d \t elapsed_time = %.2f \n", i, elapsed_time);

		//CUDA_CHECK_RETURN(cudaMemcpy(fpHost_C, fpDevice_C, stBytesCount, cudaMemcpyDeviceToHost));
		//for (size_t j = 0; j < iElemntCount; j++)
		//{
		//	printf("%.2f + %.2f = %.2f \n", fpHost_A[j],  fpHost_B[j], fpHost_C[j]);
		//}
	}

	delete[]fpHost_A;
	delete[]fpHost_B;
	delete[]fpHost_C;

	fpHost_A = nullptr;
	fpHost_B = nullptr;
	fpHost_C = nullptr;

	return 0;
}

static void CheckCudaErrorAux(const char* file, unsigned line, const char* statement, cudaError_t err)
{
	if (err == cudaSuccess)
		return;
	std::cerr << statement << " returned: "<< cudaGetErrorName(err) << "  \t : " << cudaGetErrorString(err) << "(" << err << ") at " << file << ":" << line << std::endl;
	exit(1);
}

结果:

可以看出第一次调用的时候最费时

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2213803.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【网络安全】1,600$:Auth0 错误配置

未经许可,不得转载。 文章目录 前言正文漏洞案例修复建议前言 Auth0 是一个广泛用于网站和应用程序的身份验证平台,负责管理用户身份并确保其服务的安全访问。该平台提供了多种工作流程,以无缝集成登录和注册流程。 在 Auth0 中创建新应用时,注册选项默认启用。当系统禁用…

Go 1.19.4 命令调用、日志、包管理、反射-Day 17

1. 系统命令调用 所谓的命令调用&#xff0c;就是通过os&#xff0c;找到系统中编译好的可执行文件&#xff0c;然后加载到内存中&#xff0c;变成进程。 1.1 exec.LookPath&#xff08;寻找命令&#xff09; 作用&#xff1a; exec.LookPath 函数用于在系统的环境变量中搜索可…

【每日刷题】Day139

51. N 皇后 - 力扣&#xff08;LeetCode&#xff09; //思路&#xff1a;DFS哈希。 //本题的难点就在于剪枝操作。 class Solution { public: int n; vector<vector<string>> ans; vector<string> path; bool cols[10], dig1[20], dig2[20]; void dfs(int ro…

【无标题】基于情境依赖因果影响的多智能体协作强化学习

、文章探讨了大型语言模型&#xff08;LLMs&#xff09;&#xff0c;例如GPT-4&#xff0c;是否以及在何种意义上拥有知识。作者认为&#xff0c;这些模型展现了一种称为“工具性知识”的能力&#xff0c;这种知识允许它们根据输入上下文推断任务结构&#xff0c;并在此基础上进…

appium启动hbuild打包的apk异常解决

目录 一、错误信息 二、问题解决 2.1 通过以下命令获取安装包名称&#xff1a; 2.2 这个launcher状态下的安装包名称和active&#xff0c;替换原先的安装包名称 一、错误信息 通过adb shell dumpsys activity | findstr "mResume" 命令获取的安装包信息&#xff…

2024年公路水运工程施工企业主要负责人证模拟考试题库及公路水运工程施工企业主要负责人理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年公路水运工程施工企业主要负责人证模拟考试题库及公路水运工程施工企业主要负责人理论考试试题是由安全生产模拟考试一点通提供&#xff0c;公路水运工程施工企业主要负责人证模拟考试题库是根据公路水运工程施…

芯课堂 | 使用 SWM341 系列 MCU 环境配置

SWM341系列MCU调试环境配置 SWM341 是华芯微特的其中一款 MCU&#xff0c;341 和 341内置 SDRAM 的 34S 系列&#xff0c;其内核相同。 芯片使用安谋科技“星辰”STAR-MC1 内核,基于 Arm-V8 指令集架构&#xff0c;下载烧录选 M33&#xff0c;对应的工具需要升级; 1、使用 KE…

MySQL中库的操作

目录 前言 一、查看数据库 1.1、语法 二、创建数据库 2.1、语法 2.2、自定义⼀个数据库 2.2.1、创建一个名为“aokey”的数据库 三、字符集编码和校验(排序)规则 3.1、查看数据库支持的字符集编码 3.2、查看数据库支持的排序规则 3.3、不同的字串集与排序规则对数…

芯片供电引脚为什么要放一个104电容?

每个芯片的电源都要接一个104电容是为什么? 这颗电容叫高频旁路电容&#xff0c;作用就是把电源中的高频杂波对地短路防止高频污染&#xff0c;降低电源输入对芯片的影响。 接地滤波电容&#xff0c;如果没有&#xff0c;杂波干扰非常大&#xff0c;有了这个滤波电容&#x…

Json-Rpc框架(项目设计 —— 服务端客户端 模块功能划分简介)

阅读导航 引言一、理解项目功能⭕分布式RPC服务发现/注册/订阅/创建 结构图⭕项目三大核心功能 二、服务端模块划分简介三、客户端模块划分简介 引言 在上一篇文章中&#xff0c;我们深入探讨了Json-Rpc框架中不可或缺的序列化与反序列化利器——JsonCpp库。 在本篇文章中&am…

Python酷玩之旅_如何正确使用pipreqs完成依赖导出(解决UnicodeDecodeError)

导览 前言Q&#xff1a;如何正确使用pipreqs1. 安装库2. 命令详解2.1 options2.2 path 3. 实践与问题 结语系列回顾 前言 使用python开发的应用在迁移部署的时候&#xff0c;你一定会使用pipreqs&#xff08;当然也有其他选择&#xff09;吧&#xff1f;这是一款强大的依赖管理…

【STM32CubeMX开发】-2.1-TIM_生成一个定时器中断

目录 1 Tim定时器的时钟源 2 Tim定时器的配置 2.1 中断配置 3 生成代码 4 测试结果 结尾 1 Tim定时器的时钟源 TIM1的时钟来源自APB1 Timer clocks&#xff0c;时钟树上所有总线频率均设置为了STM32F0能达到的最高频率&#xff0c;此时APB1 Timer clocks 48MHz。 2 Tim…

pdf加密怎么弄?8款热门pdf加密工具大盘点,速来收藏!(2024)

在如今&#xff0c;分享pdf文件时确保敏感信息的安全显得尤为重要。如果没有适当的保护措施&#xff0c;这些文件可能会被不法人士访问&#xff0c;从而对您的数据和声誉造成风险。为了避免这种潜在的问题&#xff0c;在Windows操作系统上加密pdf文件就显得非常有必要。如果您不…

vue3 使用 Vue Router实现前端路由控制

vue3 使用 Vue Router实现前端路由控制 **在现代Web应用中&#xff0c;前端路由控制是非常重要的一部分。它可以帮助我们将不同的页面内容展示给用户&#xff0c;同时保持用户在浏览不同页面时的连贯性。本文将介绍如何使用Vue Router来实现前端路由控制。 首先&#xff0c;我…

在Oxygen编辑器中支持数学公式

在编写文档时&#xff0c;经常需要插入公式。虽然将公式作为图片插入到文档中是可以的&#xff0c;但这会使后续的修改变得非常不便。目前&#xff0c;MathML (Mathematical Markup Language) 和 LaTeX 是两种常用的数学公式描述语言&#xff0c;它们各自具有不同的特点和适用场…

Protobuf:消息更新

Protobuf&#xff1a;消息更新 更新字段保留字段未知字段option选项 在开发中&#xff0c;需要对产品进行版本迭代。迭代前后&#xff0c;类的成员可能就会有所改动&#xff0c;一旦类成员改动&#xff0c;那么老版本的对象&#xff0c;新版本可能就无法解析&#xff0c;此时就…

ubuntu中多cuda版本兼容问题

当ubuntu中已经有老版本的cuda时&#xff0c;按正常步骤直接下载新的cuda和cudnn&#xff0c;只需要注意在下载新的cuda版本时&#xff0c;出现“A symlink already exists at /usr/local/cuda. Update to this installation?”&#xff0c;选择“no”&#xff0c;之后按如下的…

【华为HCIP实战课程十二】OSPF网络中1类2类LSA SPF详解,网络工程师

一、OSPF 1类LSA详解 1、通告者(产生LSA的设备):任何一台设备都会产生1类LSA 2、通告的范围:区域内部 3、功能和内容:产生拓扑信息和路由信息 LSA是OSPF链路状态信息的载体 4、每台OSPF路由器使用一条Router-LSA描述本区域内的链路状态信息 Type :LSA类型,Router-L…

Java学习Day45:兰喜村(Redis)

1.redis概念 1.是什么 redis&#xff08;c语言开发的高并发键值对数据库&#xff09;是nosql的一种&#xff0c;是键值存储数据库&#xff1b; 其核心概念是三高&#xff1a;高并发&#xff0c;高可用性和高扩展性&#xff1b; 优点&#xff1a;快速存取高并发 缺点&#…

Echart自定义饼图

const chartOption computed(() > {return {//与容器边距// grid: {// left: 3%,// right: 4%,// bottom: 3%,// containLabel: true// },// 自定义鼠标悬浮显示内容tooltip: {trigger: item,formatter: function (params: any) {return ${params.value} 个},textS…