CUDA之指针篇

news2024/10/2 6:41:03

CUDA教程

第一章 指针篇
第二章 cuda原理篇
第三章

随着人工智能的发展与人才的内卷,很多企业已将深度学习算法的C++部署能力作为基本技能之一。面对诸多arm相关且资源有限的设备,往往想更好的提速,满足更高时效性,必将更多类似矩阵相关运算交给CUDA处理。同时,面对市场诸多教程与诸多博客岑子不起的教程或高昂教程费用,使读者(特别是小白)容易迷糊,无法快速入手CUDA编程,实现工程化。
因此,我将结合我的工程实战经验,我将在本专栏实现CUDA系列教程,帮助读者(或小白)实现CUDA工程化,掌握CUDA编程能力。学习我的教程专栏,你将绝对能实现CUDA工程化,完全从环境安装到CUDA核函数编程,从核函数到使用相关内存优化,从内存优化到深度学习算子开发(如:nms),从算子优化到模型(以yolo系列为基准)部署。最重要的是,我的教程将简单明了直切主题,CUDA理论与实战实例应用,并附相关代码,可直接上手实战。我的想法是掌握必要CUDA相关理论,去除非必须繁杂理论,实现CUDA算法应用开发,待进一步提高,将进一步理解更高深理论。


文章目录

  • CUDA教程
  • 前言
  • 一、指针与cuda编程的关系
  • 二、指针定义
  • 三、指针运算符*与&
    • *运算符
    • &运算符
  • 四、指针示例
    • 指针赋值方法探索
    • 指针基础-数组读取
    • 指针指向地址的值的探索
  • 指向指针的指针
    • 指针使用初步探索
    • 指针的指针的图文解释


前言

CUDA依赖指针,本篇需掌握相关指针内容,为CUDA编程提供依据。


一、指针与cuda编程的关系

cuda将使用stream方式控制计算,基本使用指针的方式进行数据拷贝或者开辟内存等,为此学习cuda编码需了解指针相关基础。

具体代码展示示例如下:

cuda个人编写示例:  
 CUDA_CHECK(cudaMallocHost((void**)&img_buffer_host, max_image_size * 3));
  // prepare input data in device memory
 CUDA_CHECK(cudaMalloc((void**)&img_buffer_device, max_image_size * 3));

cuda源码示例:
extern __host__ cudaError_t CUDARTAPI cudaMallocHost(void **ptr, size_t size);
inline __device__  cudaError_t CUDARTAPI cudaMalloc(void **p, size_t s) 
{ 
  return cudaErrorUnknown;
}

以上代码为内存分配示例,可看出使用了指针,因此我们调用cuda相关函数需要大量涉及指针相关方法。

二、指针定义

指针定义:指针是一个值为内存地址的变量或者数据对象。指针变量的值是地址。

如:*p表示定义指针,实际p是指针,指针变量名为p,那么我们可以通过 p = &a,将a的地址赋值给p,因为指针存存的是地址,从而我们可以通过对p进行操作,对a进行修改等操作。

在这里插入图片描述

三、指针运算符*与&

*运算符

*运算符,叫间接运算符或叫解引用运算符,找出存储在地址的值。*运算符后面跟着一个指针名或者地址时,*给出存储在指针所指向地址的值。

如:*ptr表示指针ptr对应地址的值,与val=*ptr是等量的,而ptr=&val是等量的,&val表示变量val的地址。

&运算符

&运算符,叫做地址运算符。后跟变量名时,&给出该变量的地址。

如:变量val,&val表示变量val的地址,若定义*p的指针,可将指针指向变量使用p=&val。

四、指针示例

此部分将给出指针几个列子,我将根据这些列子说明指针实际用法与表示含义,以下列子均经过验证,可使用的方法。

在进行指针示例演示代码之前,我将在此贴出公用代码,此代码或许下面某些示例需要使用。

void Print_Pointers(int* ptr,int N) {
    for (int i = 0; i < N; i++)
    {
        std::cout << "order:\t" << i << "\tptr_value:\t" << *ptr << "\tphysical address:" << ptr << std::endl;
        ptr++;
    }
}

指针赋值方法探索

指针赋值共探索2种方法,其一在创建指针时候赋值,其二在创建指针完成后赋值,以下代码将指针指向数组,arr数组变量名表示地址,因此可直接赋值;指针p赋值也需要指向变量a的地址,因此需使用&符号获取变量a的地址,然后将地址赋给指针p。

代码如下:

void pointer_1() {
    /*  探索指针赋值方法 */
    const int N = 6;
    int arr[N];
    for (int i = 0; i < N; i++) arr[i] = i + 1; //数组赋值
    //指针第一种赋值方法
    int* ptr=nullptr ; 
    ptr = arr;
    //指针第二种赋值方法
    int *ptr2 = arr;
    
    std::cout << "output ptr1 " << std::endl;
    Print_Pointers(ptr, N);
    std::cout << "\n\noutput ptr2 " << std::endl;
    Print_Pointers(ptr2,N);

    //单独变量赋值
    int a = 20;
    int* p = &a;  
    std::cout << "\n\noutput p value: \t" <<*p<<"\tphysical address:\t"<<p<< std::endl;

}

结果显示:
在这里插入图片描述

指针基础-数组读取

指针的初始化、解引用操作以及自增,看一个有趣的语句“int *ptr = arr;”,该语句用数组名初始化指针。在这里数组名代表的是数组第一个元素的地址,之后在循环内程序会递增指针以指向数组的后面几个元素。

代码如下:

void pointer_1() {
    const int N = 6;
    int arr[N];
    for (int i = 0; i < N; i++) arr[i] = i + 1; //数组赋值
    int* ptr = arr; //构建指针
    for (int i = 0; i < 5; i++)
    {
        std::cout << "ptr_value_" <<i<< ":\t" << *ptr << std::endl;;
        ptr++;  
    } 
}

结果显示:

在这里插入图片描述

指针指向地址的值的探索

此部分探索地址指针指向的值变化:

1.通过指针更改值,将指针赋值为num的地址,通过更改p的指针来更改指针指向num地址的值p=*p+20,该物理地址的值更改,而num存的值的物理地址为p,因此也更改了num的值;

2.通过变量更改值,将num=30,更改num的值,而指针p保存指向num的地址,地址不变情况,通过*p查看地址的值,因此为num更改的值30。

代码如下:

void pointer_3() {
    int num = 4;
    int* p = &num;
    cout << "*p:\t" <<*p<<"\t p address:\t"<<p<<"\tnum value:\t"<<num<<"\tnum address:\t"<<num << endl;

    *p = *p + 20; //通过指针更改地址的值
    cout << "*p:\t" << *p << "\t p address:\t" << p << "\tnum value:\t" << num << "\tnum address:\t" << num << endl;
    num = 30; //更改变量值
    cout << "*p:\t" << *p << "\t p address:\t" << p << "\tnum value:\t" << num << "\tnum address:\t" << num << endl;


}

结果显示:
在这里插入图片描述

指向指针的指针

定义:指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链。 指针的指针就是将指针的地址存放在另一个指针里面。

通俗解释:一个指针包含一个变量的地址。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的物理位置。

在这里插入图片描述
一个指向指针的指针变量必须如下声明,即在变量名前放置两个星号。

指针使用初步探索

探索指针的指针 值与地址之间的关系:

1.指针的指针赋值,结果中看指针的指针p2与p3打印值*p2/*p3与地址p2/p3输出一致 ,则赋值方法与指针赋值差不多,但需要&符号赋值。

2.指针的指针p2说明,前提p1指针指向地址000000E9AC0FF914,并保存地址,本身p1指针有自己地址,为此p2指针指向p1指针的地址,*p2表示p1的值也为num的地址。

3.指针p2的**p2与*p2说明,p2是指针p1的值,而p1的值是num的地址,在前加表示取p1值(num)的值为num值4。

实际理解与单指针*p1一样,只需记住此时p1的值为num的地址,而本身p1存在自身地址保存值(num地址)。

void pointer_4() {
    int num = 4;
    int* p1 = &num;
    //指针的指针第一种赋值方法
    int** p2=&p1 ;
    //指针的指针第二种赋值方法
    int** p3;
    p3 = &p1;

    cout << "num value:\t" << num << "\t num address:\t" << &num << endl;
    cout << "p1 value:\t" << *p1 << "\t p1 address:\t" << p1 << endl;
    cout << "p2 value:\t" << *p2 << "\t p2 address:\t" << p2 << endl;
    cout << "p3 value:\t" << *p3 << "\t p3 address:\t" << p3 << endl;

    cout << "p2 value:\t" << **p2 << "\t p2 address:\t" << *p2  << endl; 
}

结果显示:

在这里插入图片描述

指针的指针的图文解释

假设变量num的值为4,定义指针*p1与指针的指针**p2,p1指向num,p2指向p1,其示意图如下:
在这里插入图片描述
解释如下:

1.p2与p1本质是指针,因此需指向地址,从图中可看出p2的值value3指向address2,p1的值value2指向address1。

2.p2、p1与num本身有自己的地址,分别为address3、address2与address1。

3.定义的**p2与*p定义完后,p2与p1分别为地址address3与address2,即p2=address3,p1=address2。

4.使用*获得p2与p1指向指针的地址的值,从图可看出p1的值value指向地址address1,且地址address1的值为value1=4,则 *p1=4;

同理,p2的值value3指向地址address2,且address2的值为value2=address1,则*p2=address1。

5.如何通过p2获得num的值呢?从4可看出p2=address1,而address1的值为value1=4,则需再次使用(*p2)的方式再次获得address1的值即可,

则**p2=value1=4。


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

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

相关文章

【高危】Spring Security鉴权规则错误配置风险

漏洞描述 Spring Security 是一套为基于Spring的应用程序提供说明性安全保护的安全框架。 在 Spring Security 受影响的版本中&#xff0c;由于 Spring Security 的授权规则会应用于整个应用程序上下文&#xff0c;当应用程序中包含多个servlet&#xff0c;并且其中一个为Dis…

测试必备工具之抓包神器 Charles 如何抓取 https 数据包?

前言 之前我们发过一篇文章讲解了Charles抓包工具的基本使用&#xff0c;有需要的小伙伴可以去看上一篇文章。 之前文章讲的数据包主要是http协议&#xff0c;大家可以看到数据包并直接显示具体详细的内容&#xff1a; 但是如果抓到的是https的报文&#xff0c;是没有办法直…

Redis DeskTop Manager 使用教程

简单粗暴的介绍一下&#xff0c;以及在工作中如何去使用工具管理我们的Redis&#xff0c;更加详细及深入的使用方法欢迎大家评论区讨论&#xff0c;我也和大家一起学习。 简介&#xff1a; Redis Desktop Manager (RDM) 是一个开源的图形化 Redis 数据库管理工具&#xff0c;…

erp什么意思,erp系统软件到底是干嘛用的?

企业资源计划 (ERP) 的定义 企业资源计划 (ERP) 是指组织用于管理日常业务活动的一套软件&#xff0c;这些活动包括会计、采购、项目管理、风险管理和合规性、供应链运营等等。完整的 ERP 套件还包括企业绩效管理软件&#xff0c;用于帮助企业针对财务结果制定计划和编制预算…

react-native项目安卓版本升级 compileSdkVersion 29->31

因为 react-native-ble-manager添加过程及碰到的问题 依赖 https://github.com/innoveit/react-native-ble-manager 参考&#xff1a;https://blog.csdn.net/withings/article/details/71378562 iOS 按react-native-ble-manager 文档在 【Info.plist】加了key之后能正常使用…

Vue学习Day1——小案例快速入门Vue指令

一、Vue简介 概念&#xff1a;是一套 构建用户界面 的 渐进式 框架 Vue2官网&#xff1a;https://v2.cn.vuejs.org/ 1、什么是渐进式 所谓渐进式就是循序渐进&#xff0c;不一定非得把Vue中的所有API都学完才能开发Vue&#xff0c;可以学一点开发一点 Vue的两种开发方式&…

【图像分割】基于蜣螂优化算法DBO的Otsu(大津法)多阈值电表数字图像分割 电表数字识别【Matlab代码#51】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第5节&#xff1a;资源获取】1. 原始蜣螂优化算法1.1 滚球行为1.2 跳舞行为1.3 繁殖行为1.4 偷窃行为 2. 多阈值Otsu原理3. 部分代码展示4. 仿真结果展示5. 资源获取说明 【可更换其他算法&#xff0c;获取资源请见文章第…

UDS之27服务

SecurityAccess&#xff08;0x27&#xff09;—— 安全访问 这个服务的目的是为那些限制访问&#xff0c;以及和排放、安全相关的一些服务和数据提供一些访问权限来保护数据。 此服务执行步骤如下&#xff1a; &#xff08;1&#xff09;Client请求一个种子&#xff08;Seed…

一.安装k8s环境

1.初始操作 默认3台服务器都执行 # 关闭防火墙 systemctl stop firewalld systemctl disable firewalld# 关闭selinux sed -i s/enforcing/disabled/ /etc/selinux/config # 永久 setenforce 0 # 临时# 关闭swap swapoff -a # 临时 sed -ri s/.*swap.*/#&/ /etc/fstab…

国标GB28181视频监控平台EasyGBS无法播放,抓包返回ICMP的排查过程

国标GB28181视频平台EasyGBS是基于国标GB/T28181协议的行业内安防视频流媒体能力平台&#xff0c;可实现的视频功能包括&#xff1a;实时监控直播、录像、检索与回看、语音对讲、云存储、告警、平台级联等功能。国标GB28181视频监控平台部署简单、可拓展性强&#xff0c;支持将…

【Docker】基本概念和底层技术

Docker 1 什么是 Docker Docker 是一种容器技术。只要开发者将其应用和依赖包进行打包&#xff0c;放入到一个轻量级的、可移植的容器中&#xff0c;就能发布到任何流行的 linux 机器上。 Docker 的要素&#xff1a; image 镜像&#xff1a;静态的container 容器&#xff1a…

多线程-synchronized

文章目录 synchronized同步方法synchronized同步静态方法synchronized同步代码块 Java的多线程允许同时做多件事情。但是&#xff0c;两个及两个以上的线 程彼此互相影响的问题也就出现了。如果不防范这种冲突&#xff0c;就可能发 生两个用户购买了同一个座位的火车票&#xf…

【Nodejs】nodejs内置模块(中)

1.路劲处理模块 path 1.1 模块概览 在nodejs中&#xff0c;path是个使用频率很高&#xff0c;但却让人又爱又恨的模块。部分因为文档说的不够清晰&#xff0c;部分因为接口的平台差异性。将path的接口按照用途归类&#xff0c;仔细琢磨琢磨&#xff0c;也就没那么费解了。 1.…

【Ruoyi】静态资源映射

这里写自定义目录标题 帮助链接核心代码分析 帮助链接 SpringBoot–WebMvcConfigurer详解Ruoyi自定义资源映射 核心代码 /*** 通用配置* * author wiserice*/ Configuration public class ResourcesConfig implements WebMvcConfigurer {Autowiredprivate RepeatSubmitInter…

【代码随想录day19】路径总和

题目 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 叶子节点 是指没有…

ip校园广播音柱特点

ip校园广播音柱特点IP校园广播音柱是一种基于IP网络技术的音频播放设备&#xff0c;广泛应用于校园、商业区、公共场所等地方。它可以通过网络将音频信号传输到不同的音柱设备&#xff0c;实现远程控制和集中管理。IP校园广播音柱具备以下特点和功能&#xff1a;1. 网络传输&am…

解决嵌入式中QTableWidget双击出现空白QTableWidgetItem输入

目录 所说BUG现象解决方式1方式2全部内容 效果 今天突然想起在上个公司解决的一个BUG 嵌入式中QTableWidget一般只能看数据不能编辑&#xff0c;或者是选择 所以双击出现空白QTableWidgetItem是不允许的 所说BUG现象 解决 在空白的单元格中&#xff0c;添加不可编辑的QTableWid…

工业物联网网关让PLC数据手机端监控和报警更加简单

在传统的工厂管理中&#xff0c;我们想要看到现场设备的实时数据&#xff0c;必须在控制室内通过工控机、电脑、触摸屏等这些上位机设备才能看到&#xff0c;同理PLC维护也需要工程师在现场进行编程调试工作&#xff0c;非常不方便。 随着工业物联网的发展&#xff0c;作为设备…

一个废话巨多的 printf 题

网友给了一个题&#xff0c;这题是个格式化字符串漏洞的题。很有代表性&#xff0c;专门把这题说一下。其中为入门级的多说些废话。 附1&#xff1a;gdb 作pwn题是绕不开gdb的&#xff0c;而gdb本身不方便用&#xff0c;于是有了各种插件pwngdb,peda,gdbinit,gef都很牛&#…

Kafka-配置Kerberos安全认证(JDK8、JDK11)

一、相关配置 1、JAAS 配置文件 KafkaClient {com.sun.security.auth.module.Krb5LoginModule requireduseKeyTabtruestoreKeytrueserviceName"kafka"keyTab"D:/code/demo/conf/kafka.service.keytab"principal"kafka/hdp-1"; }; 2、keytab 文…