[9] CUDA性能测量与错误处理

CUDA性能测量与错误处理

  • 讨论如何通过CUDA事件来测量它的性能
  • 如何通过CUDA代码进行调试

1.测量CUDA程序的性能

1.1 CUDA事件

  • CPU端的计时器可能无法给出正确的内核执行时间
  • CUDA事件等于是在你的CUDA应用运行的特定时刻被记录的时间戳,通过使用CUDA事件API,由GPU来记录这个时间戳
  • 使用CUDA测量时间需要两个步骤:创建事件和记录事件,记录事件(开始时间与结束时间)
  • 代码如下:
#include "stdio.h"
#include<iostream>
#include <cuda.h>
#include <cuda_runtime.h>
//Defining number of elements in Array
#define N	50000
//Defining Kernel function for vector addition
__global__ void gpuAdd(int* d_a, int* d_b, int* d_c) {
	//Getting Thread index of current kernel

	int tid = threadIdx.x + blockIdx.x * blockDim.x;
	while (tid < N)
	{
		d_c[tid] = d_a[tid] + d_b[tid];
		tid += blockDim.x * gridDim.x;
	}

}

int main(void) {
	//Defining host arrays
	int h_a[N], h_b[N], h_c[N];
	//Defining device pointers
	int* d_a, * d_b, * d_c;
    
    //----------创建事件记录起止时间---------------------
	cudaEvent_t e_start, e_stop;
	cudaEventCreate(&e_start);
	cudaEventCreate(&e_stop);
    //第一次记录时间戳
	cudaEventRecord(e_start, 0);
	
	// allocate the memory
	cudaMalloc((void**)&d_a, N * sizeof(int));
	cudaMalloc((void**)&d_b, N * sizeof(int));
	cudaMalloc((void**)&d_c, N * sizeof(int));
	//Initializing Arrays
	for (int i = 0; i < N; i++) {
		h_a[i] = 2 * i * i;
		h_b[i] = i;
	}
	// Copy input arrays from host to device memory
	cudaMemcpy(d_a, h_a, N * sizeof(int), cudaMemcpyHostToDevice);
	cudaMemcpy(d_b, h_b, N * sizeof(int), cudaMemcpyHostToDevice);
	//Calling kernels passing device pointers as parameters
	gpuAdd << <512, 512 >> > (d_a, d_b, d_c);
	//Copy result back to host memory from device memory
	cudaMemcpy(h_c, d_c, N * sizeof(int), cudaMemcpyDeviceToHost);
	cudaDeviceSynchronize();
	//再次记录时间戳
	cudaEventRecord(e_stop, 0);
	//等待所有GPU工作都完成
	cudaEventSynchronize(e_stop);
	
	float elapsedTime;
	//计算时间插值
	cudaEventElapsedTime(&elapsedTime, e_start, e_stop);
	printf("Time to add %d numbers: %3.1f ms\n", N, elapsedTime);

	int Correct = 1;
	printf("Vector addition on GPU \n");
	//Printing result on console
	for (int i = 0; i < N; i++) {
		if ((h_a[i] + h_b[i] != h_c[i]))
		{
			Correct = 0;
		}

	}
	if (Correct == 1)
	{
		printf("GPU has computed Sum Correctly\n");
	}
	else
	{
		printf("There is an Error in GPU Computation\n");
	}
	//Free up memory
	cudaFree(d_a);
	cudaFree(d_b);
	cudaFree(d_c);
	return 0;
}

1.2 NVIDIA Visual Profiler

  • 如果你在程序中使用了CUDA,代码的性能并未提升,在这种情况下,能够可视化地查看代码的哪些部分花费了最长的时间完成将非常有用,这叫剖析内核执行代码
  • 英伟达提供了以上用途的工具 nvvp ,就在标准的CUDA安装包里,在电脑的如下路径可以被找到:C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.7\libnvvp
    在这里插入图片描述
  • 执行它需要安装java环境,即安装jdk8即可,可以去官网下载,也可以从我的链接 jdk8下载,然后需要配置环境变量C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.7\extras\CUPTI\lib64 C:\Program Files\Java\jdk-1.8\bin
    在这里插入图片描述
  • 打开nvvp 会出现如下窗口,此工具会分析你的代码执行过程,采集GPU上的性能数据,运行结束后会给你一个详细的报告,包括每个内核的执行时间,代码中每个详细操作的时间戳,以及代码存储器的使用情况
    在这里插入图片描述
  • 想要得到详细报告,可依次点击 File -> New Session,然后在弹出的对话框中选择程序的.exe文件
    在这里插入图片描述
  • Profiler 是分析内核执行情况的重要工具,它也可以用来比较两个内核的性能。它会告诉你就是是代码里的何种操作拉低了性能

2. CUDA中的错误处理

  • 如果系统中没有可用的GPU设备怎么办?显存不足怎么办?
  • 学会在CUDA程序里边添加错误处理代码很有好处
#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>

__global__ void gpuAdd(int *d_a, int *d_b, int *d_c) {
	*d_c = *d_a + *d_b;
}
int main()
{
	//Defining host variables
	int h_a, h_b, h_c;
	//Defining Device Pointers
	int *d_a, *d_b, *d_c;
	//Initializing host variables
	h_a = 1;
	h_b = 4;

    //定义错误结果变量
    cudaError_t cudaStatus;
    // Allocate GPU buffers for three vectors (two input, one output)    .
    cudaStatus = cudaMalloc((void**)&d_c, sizeof(int));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }
	cudaStatus = cudaMalloc((void**)&d_a, sizeof(int));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    cudaStatus = cudaMalloc((void**)&d_b, sizeof(int));
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMalloc failed!");
        goto Error;
    }

    // Copy input vectors from host memory to GPU buffers.
    cudaStatus = cudaMemcpy(d_a,&h_a, sizeof(int), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

    cudaStatus = cudaMemcpy(d_b, &h_b, sizeof(int), cudaMemcpyHostToDevice);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }

    // Launch a kernel on the GPU with one thread for each element.
    gpuAdd<<<1, 1>>>(d_a, d_b, d_c);

    // Check for any errors launching the kernel
    cudaStatus = cudaGetLastError();
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "addKernel launch failed: %s\n", cudaGetErrorString(cudaStatus));
        goto Error;
    }
    
    // Copy output vector from GPU buffer to host memory.
    cudaStatus = cudaMemcpy(&h_c, d_c, sizeof(int), cudaMemcpyDeviceToHost);
    if (cudaStatus != cudaSuccess) {
        fprintf(stderr, "cudaMemcpy failed!");
        goto Error;
    }
	printf("Passing Parameter by Reference Output: %d + %d = %d\n", h_a, h_b, h_c);
Error:
    cudaFree(d_c);
    cudaFree(d_a);
    cudaFree(d_b);
    
    return 0;
}
  • -----------------------END----------------------------

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

总结常见漏洞的代码审计方法

前言 这篇文章主要是总结一下在安全工作中常见漏洞的代码审计方法&#xff0c;以及修复方案&#xff0c;希望能对初学代码审计小伙伴们有所帮助&#xff0c;笔芯♥️ 代码审计的思路 通常做代码审计都是检查敏感函数的参数&#xff0c;然后回溯变量&#xff0c;判断变量是否可…

【Linux】权限的理解之权限掩码(umask)

目录 前言 一、利用八进制数值表示文件或目录的权限属性 二、系统默认的权限掩码和权限掩码的作用原理 三、分析权限掩码改变文件或目录的权限属性 前言 权限掩码是由4个数字组合而成的&#xff0c;默认的第一位数字是0&#xff1b;后三位数字分别由八进制位数字组成。权限…

贪心算法[1]

首先用最最最经典的部分背包问题来引入贪心的思想。 由题意可知我们需要挑选出价值最大的物品放入背包&#xff0c;价值即单位价值。 我们需要计算出每一堆金币中单位价值。金币的属性涉及两个特征&#xff0c;重量和价值。 所以我们使用结构体。 上代码。 #include <i…

安全术语 | 软件包purl详解:跨工具、数据库、API和语言之间可靠地识别和定位软件包

软件包URL&#xff08;purl&#xff0c;Package URL&#xff09;是一个URL字符串&#xff0c;用于在编程语言、包管理器、包约定、工具、API和数据库中以最通用和统一的方式识别和定位软件包。purl是对现有方法进行标准化的尝试&#xff0c;以可靠地识别和定位软件包。 有望取代…

MagicLens:新一代图像搜索技术和产品形态

MagicLens&#xff1a;Self-Supervised Image Retrieval with Open-Ended Instructions MagicLens: 自监督图像检索与开放式指令 作者&#xff1a;Kai Zhang&#xff0c; Yi Luan&#xff0c; Hexiang Hu&#xff0c; Kenton Lee&#xff0c; Siyuan Qiao&#xff0c; Wenhu …

vue组件-----路由系统

能够说出单页面概念和优缺点能够掌握vue-router路由系统能够掌握声明式导航和编程式导航能够掌握路由嵌套和守卫 一.Vue路由简介和基础使用 1.生活中的路由 目标&#xff1a;设备和ip的映射关系 2.nodejs路由 目标&#xff1a;接口和服务的映射关系 3.前端路由 目标&#…

短视频内容创意方法有哪些?成都科成博通文化传媒公司

短视频内容创意方法有哪些&#xff1f; 随着移动互联网的迅猛发展&#xff0c;短视频平台已成为人们日常生活中不可或缺的一部分。短视频以其短平快的特点&#xff0c;迅速吸引了大量用户。然而&#xff0c;面对海量的短视频内容&#xff0c;如何让自己的作品脱颖而出&#xf…

【Linux】Linux的权限_2 + Linux环境基础开发工具_1

文章目录 三、权限3. Linux权限管理修改文件的拥有者和所属组 4. 文件的类型5. 权限掩码 四、Linux环境基础开发工具1. yumyum 工具的使用 未完待续 三、权限 3. Linux权限管理 修改文件的拥有者和所属组 在上一节我们讲到如何更改文件的访问权限&#xff0c;那我们需要更改…

二十九、openlayers官网示例DeclutterGroup解析——避免矢量图层的文字重叠

官网demo地址&#xff1a; Declutter Group 这篇说的是如何设置矢量图层上多数据点文字不重叠。 主要是属性declutter &#xff0c;用于处理矢量图层上重叠的标注和符号&#xff0c;为true时启用去重叠功能。所有矢量特征的标注和符号都会被处理以避免重叠。false则与之相反。…

提升(或降低)插入的内容的位置:\raisebox

\raisebox 是 LaTeX 中的一个命令&#xff0c;用于提升&#xff08;或降低&#xff09;插入的内容&#xff08;如文本、图像等&#xff09;的位置。该命令可以用于调整垂直位置&#xff0c;使内容相对于周围内容上下移动。 语法如下&#xff1a; \raisebox{<distance>}…

宝藏网站推荐-封面图片生成器

封面图片生成器&#xff1a;封面图生成器 | 太空编程 (spacexcode.com)[https://spacexcode.com/coverview] 由来 最近爱上了写文案&#xff0c;在网上冲浪的时候发现一个宝藏网站。Spacecode&#xff0c;一个大神维护的个人网站&#xff0c;含有前端知识库、个人博客及他做…

轻松拿捏C语言——自定义类型之【结构体】

&#x1f970;欢迎关注 轻松拿捏C语言系列&#xff0c;来和 小哇 一起进步&#xff01;✊ &#x1f389;创作不易&#xff0c;请多多支持&#x1f389; &#x1f308;感谢大家的阅读、点赞、收藏和关注&#x1f495; &#x1f339;如有问题&#xff0c;欢迎指正 1. 结构体类型的…

攻击同学网络,让同学断网

技术介绍&#xff1a;ARP欺骗 ARP欺骗&#xff08;ARP spoofing&#xff09;是一种网络攻击技术&#xff0c;它通过伪造ARP&#xff08;地址解析协议&#xff09;响应包来欺骗目标设备&#xff0c;使其将网络流量发送到攻击者指定的位置。具体操作步骤如下&#xff1a; 攻击者…

C# 中 async 与 await 关键字详解

async 和 await 关键字的作用是使方法能够异步执行并等待异步操作的完成。&#xff08;最重要的一点是记住 “异步执行”与“等待异步操作完成”&#xff0c;不是等待主线程操作完成&#xff09; async 修饰符可将 方法、lambda 表达式或匿名方法指定为异步。 async 关键字用于…

MySQL:数据库基础操作

一、MySQL的机制 相信翻到这篇文章的你&#xff0c;应该也是来怀着大大的好奇&#xff0c;来学习MySQL这门语言&#xff0c;那么&#xff0c;现在&#xff0c;就让我和大家一起来学习这门语言吧&#xff01; 这此之前&#xff0c;我们先要了解一个事实&#xff0c;MySQL其实是划…

微服务架构-分支微服务设计模式

微服务架构-分支微服务设计模式 这种模式是聚合器模式的扩展&#xff0c;允许同时调用两个微服务链 分支微服务设计模式是一种用于构建大型系统的微服务架构模式&#xff0c;其核心思想是 将复杂的业务逻辑拆解为多个小的、相互独立的子系统&#xff0c;每个子系统由一个或多…

【iOS】didReceiveMemoryWarning实例方法

iPhone下每个App可用的内存是被限制的&#xff0c;如果一个App使用的内存超过20M&#xff0c;则系统会向该App发送Memory Warning&#xff08;内存警告&#xff09;消息&#xff0c;收到此消息后&#xff0c;App必须正确处理&#xff0c;否则可能出错或出现内存泄漏。 目录 流程…

代码随想录算法训练营day14|二叉树的递归遍历、二叉树的迭代遍历、二叉树的统一迭代法

二叉树的递归遍历 首先需要明确的一点是&#xff0c;前序中序和后序在二叉树的递归遍历中的区别仅在于递归函数中操作的顺序&#xff0c;前序是在遍历一个节点的左右子树前进行操作&#xff0c;中序是在遍历一个节点的左子树后进行操作再遍历右子树&#xff0c;而后序是在遍历…

3D点云焊缝提取 平面交线 投影

文章目录 1. 效果2. 思路3. 源码 1. 效果 2. 思路 计算点云法向量&#xff1b;计算点云位姿Pose;翻转Pose中的Z轴方向&#xff0c;使其一致&#xff1b;通过Pose的Z轴对点云进行方向过滤&#xff1b;对点云聚类&#xff1b;根据目标点云的高度提取目标点云&#xff1b;提取两块…

云计算-Amazon S3

亚马逊S3&#xff08;Amazon S3&#xff09; 亚马逊S3是一种云对象存储设施。我们将使用的对象将是您在个人计算机上常用的文件。亚马逊S3产品旨在可扩展到实际无限数量的对象和无限大小的对象&#xff0c;但我们在本实验室的练习中只会使用少量对象。当存储许多对象时&#xf…