第四章 kernel函数基础篇

news/2024/5/12 7:14:32/文章来源:https://blog.csdn.net/weixin_38252409/article/details/132109555

cuda教程目录

第一章 指针篇
第二章 CUDA原理篇
第三章 CUDA编译器环境配置篇
第四章 kernel函数基础篇
第五章 kernel索引(index)篇
第六章 kenel矩阵计算实战篇
第七章 kenel实战强化篇
第八章 CUDA内存应用与性能优化篇
第九章 CUDA原子(atomic)实战篇
第十章 CUDA流(stream)实战篇
第十一章 CUDA的NMS算子实战篇
第十二章 YOLO的部署实战篇
第十三章 基于CUDA的YOLO部署实战篇

cuda教程背景

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

cuda教程内容

第一章到第三章探索指针在cuda函数中的作用与cuda相关原理及环境配置;

第四章初步探索cuda相关函数编写(globaldevice、__host__等),实现简单入门;

第五章探索不同grid与block配置,如何计算kernel函数的index,以便后续通过index实现各种运算;

第六、七章由浅入深探索核函数矩阵计算,深入探索grid、block与thread索引对kernel函数编写作用与影响,并实战多个应用列子(如:kernel函数实现图像颜色空间转换);

第八章探索cuda内存纹理内存、常量内存、全局内存等分配机制与内存实战应用(附代码),通过不同内存的使用来优化cuda计算性能;

第九章探索cuda原子(atomic)相关操作,并实战应用(如:获得某些自加索引等);

第十章探索cuda流stream相关应用,并给出相关实战列子(如:多流操作等);

第十一到十三章探索基于tensorrt部署yolo算法,我们首先将给出通用tensorrt的yolo算法部署,该部署的前后处理基于C++语言的host端实现,然后给出基于cuda的前后处理的算子核函数编写,最后数据无需在gpu与host间复制操作,实现gpu处理,提升算法性能。

目前,以上为我们的cuda教学全部内容,若后续读者有想了解知识,可留言,我们将根据实际情况,更新相关教学内容。

大神忽略


文章目录

  • cuda教程目录
  • cuda教程背景
  • cuda教程内容
  • 前言
  • 一、global、device、host的含义
    • 1、global函数
    • 2、device函数
    • 3、host函数
  • 二、host、global、device函数关系
    • 1、host调用global函数
      • 2、global调用device函数
      • 3、host调用特殊device函数
  • 三、host、global、device函数关系结论
    • 1、函数与设备关系结论
    • 2、函数间调用形式结论
  • 四、整体代码


前言

本章开始,我们正式进入编程环节。本章介绍cuda编程基础,host或device端如何调用函数,重点说明global、device与host限定词的使用。


一、global、device、host的含义

CUDA是通过函数类型的限定词区别函数是否为host或device调用函数,主要以下三个函数类型限定词。

1、global函数

global函数:在device上执行,从host中调用,返回类型必须是void,不支持可变参数,不能成为类成员函数。且__global__修饰的函数用<<<>>>的方式调用,注意用__global__定义的kernel是异步的,这意味着host不会等待kernel执行完就执行下一步。
__global__实际为核函数,后面将有大量使用列子。以下说明核函数形式与参数:

运行时API通过在函数名称和参数列表之间插入<<<Dg, Db, Ns, S>>>的形式来指定。

Dg 的类型为dim3,指定网格的维度和大小,Dg.x * Dg.y 等于所发射的块数量;
Db 的类型为dim3,指定各块的维度和大小,Db.x * Db.y *Db.z 等于各块的线程数量;
Ns 的类型为size_t,指定各块为此调用动态分配的共享存储器(除静态分配的存储器之外),这些动态分配的存储器可供声明为动态数组的其他任何变量使用,Ns 是一个可选参数,默认值为0;
S 的类型为cudaStream t,指定相关流;S 是一个可选参数,默认值为0。

2、device函数

device函数:在device上执行,单仅可以从device中调用,不可以和__global__同时用。

3、host函数

host函数:在host上执行,仅可以从host上调用,一般省略不写,不可以和__global__同时用,但可和__device__同时使用,此时函数会在device和host都编译。

二、host、global、device函数关系

结论:host能调用global函数,global能调用device函数

1、host调用global函数

host调用global函数,类似平常普通函数调用方式,但每个global函数需要<<<Dg, Db, Ns, S>>>参数,代码如下:

test_kernel << <dim3(1), dim3(m*n), 0, nullptr >> > (g_a, g_c);

2、global调用device函数

device是设备上使用的函数,一般只能被global核函数调用,代码如下:

float sigmoid_host(float x) {float y= 1 / (1 + exp(-x));return y;
}
__device__  float sigmoid(float x) {float y= 1 / (1 + exp(-x));return y;
}
__global__ void test_kernel(float* a, float* c) {int idx = threadIdx.x ;c[idx] = sigmoid(a[idx]); //正确方式//c[idx] = sigmoid_host(a[idx]);//绝对错误,无法调用,即:global函数无法调用host函数,只能调用devices函数
}

注意:gloabal 函数绝对无法调用host函数

执行结果如下图:
在这里插入图片描述

3、host调用特殊device函数

一般而言,device只能被global函数调用,但有一种特色device函数可被host函数调用,即:函数被host限定词使用,如下sigmod_device_host函数形式,能被host函数调用。具体实现代码如下:

__device__ __host__  float sigmoid_device_host(float x) {float y = 1 / (1 + exp(-x));return y;
}
void host2device(){float y=sigmoid_device_host(1.25);std::cout << y << endl;std::cout << "success:host calling  device+host  " << endl;//以下执行失败   try {float y = sigmoid_host(1.25);throw std::runtime_error("error: fail");   } catch (std::runtime_error err) {std::cout << "fail:host calling device" << endl;}}

执行结果如下:
在这里插入图片描述

三、host、global、device函数关系结论

1、函数与设备关系结论

a、host函数无法调用device函数,但可调用__device__ __host__的2个限定函数。

b、device函数在设备gpu上执行,host函数在cpu上执行;

c、global函数通过cpu调用,而global通常为kernel函数,是需要将数据转到gpu上运行。

2、函数间调用形式结论

a、global函数无法调用host函数,可调用device函数;

b、host函数可调用host函数与global函数,可调用组合__device__ __host__函数(实际调用host函数);

c、device函数可调用device函数;

四、整体代码

函数间调用关系代码如下:
注:附数源码链接[点击这里](https://github.com/tangjunjun966/cuda-tutorial-master)

#include <iostream>
#include <time.h>
#include "opencv2/highgui.hpp"  //实际上在/usr/include下
#include "opencv2/opencv.hpp"
#include "device_launch_parameters.h"
#include <cuda_runtime_api.h>
using namespace cv;
using namespace std;
/*************************************第四节-CUDA函数基础**********************************************/
float sigmoid_host(float x) {float y= 1 / (1 + exp(-x));return y;
}
__device__  float sigmoid(float x) {float y= 1 / (1 + exp(-x));//float y = sigmoid_host(x);return y;
}
__global__ void test_kernel(float* a, float* c) {int idx = threadIdx.x ;c[idx] = sigmoid(a[idx]); //正确方式//c[idx] = sigmoid_host(a[idx]);//绝对错误,无法调用,即:global函数无法调用host函数,只能调用devices函数  
}void Print_dim(float* ptr, int N) {for (int i = 0; i < N; i++){std::cout << "value:\t" << ptr[i] << std::endl;}
}
void init_variables_float(float* a,  int m, int n) {//初始化变量std::cout << "value of a:" << endl;for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {a[i * n + j] = rand()/4089 ;std::cout << "\t" << a[i * n + j];}std::cout << "\n";}
}
void global2device() {const int m = 4;const int n = 2;//分配host内存float* a, * c;cudaMallocHost((void**)&a, sizeof(float) * m * n);cudaMallocHost((void**)&c, sizeof(float) * m * n);//变量初始化init_variables_float(a, m, n);// 分配gpu内存并将host值复制到gpu变量中float* g_a;cudaMalloc((void**)&g_a, sizeof(float) * m * n);cudaMemcpy(g_a, a, sizeof(float) * m * n, cudaMemcpyHostToDevice);float* g_c;cudaMalloc((void**)&g_c, sizeof(float) * m * n);test_kernel << <dim3(1), dim3(m * n), 0, nullptr >> > (g_a, g_c);cudaMemcpy(c, g_c, sizeof(float) * m * n, cudaMemcpyDeviceToHost);Print_dim(c, m * n);
}__device__ __host__  float sigmoid_device_host(float x) {float y = 1 / (1 + exp(-x));return y;
}
void host2device(){float y=sigmoid_device_host(1.25);std::cout << y << endl;std::cout << "success:host calling  device+host  " << endl;//以下执行失败   try {float y = sigmoid_host(1.25);throw std::runtime_error("error: fail");   } catch (std::runtime_error err) {std::cout << "fail:host calling device" << endl;}
}void function_criterion_main() {//global2device();//host<--global<--devicehost2device();
}

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

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

相关文章

C++ 派生类的拷贝构造函数

当存在类的继承关系时&#xff0c;对于一个类&#xff0c;如果程序员没有编写拷贝构造函数&#xff0c;编译系统会在必要时自动生成一个隐含的拷贝构造函数&#xff0c;这个隐含的拷贝构造函数会自动调用基类的拷贝构造函数&#xff0c;然后对派生类新增的成员对象一一执行拷贝…

RabbitMQ的6种工作模式

RabbitMQ的6种工作模式 官方文档&#xff1a; http://www.rabbitmq.com/ https://www.rabbitmq.com/getstarted.html RabbitMQ 常见的 6 种工作模式&#xff1a; 1、simple简单模式 1)、消息产生后将消息放入队列。 2)、消息的消费者监听消息队列&#xff0c;如果队列中…

《MySQL高级篇》十五、其他数据库日志

文章目录 1. MySQL支持的日志1.1 日志类型1.2 日志的弊端 2. 慢查询日志(slow query log)3. 通用查询日志3.1 问题场景3.2 查看当前状态3.3 启动日志3.4 查看日志3.5 停止日志3.6 删除\刷新日志 4. 错误日志(error log)4.1 启动日志4.2 查看日志4.3 删除\刷新日志4.4 MySQL8.0新…

C语言多级指针

#include "stdio.h" #include <stdlib.h>int main() {int a 10;//*p int a int *pint* p &a;int** q &p;//int** q int *(*q) int *(q) a//int**q int*(*q) int*(&a) int*&a aint*** k &q;//分析&#xff1a;首先k是个变量&…

STM32--综述

文章目录 前言STM32简介STM32F103C8T6系统结构Keil软件安装注意事项新建工程操作流程 前言 本专栏将学习B站江协科技的STM32入门教程&#xff0c;通过自身理解和对老师的总结所写的博客专栏。 STM32简介 STM32是意法半导体&#xff08;STMicroelectronics&#xff09;公司推…

【计算机视觉 | 图像分割】arxiv 计算机视觉关于图像分割的学术速递(8 月 4 日论文合集)

文章目录 一、分割|语义相关(6篇)1.1 Point2Mask: Point-supervised Panoptic Segmentation via Optimal Transport1.2 Weakly Supervised 3D Instance Segmentation without Instance-level Annotations1.3 LiDAR-Camera Panoptic Segmentation via Geometry-Consistent and S…

ACL访问控制列表

ACL介绍 acl: 访问控制列表 步骤&#xff1a; 创建一个访问控制规则调用这个规则 ACL的分类和标识 ACL的匹配顺序以及匹配结果 拓扑图 配置 # 首先通过三层交换的实验做一次 ....## 检测ip地址 display ip interface brief## 在交换机2上做配置 [S2]acl name test ?IN…

【神经网络手写数字识别-最全源码(pytorch)】

Torch安装的方法 学习方法 1.边用边学&#xff0c;torch只是一个工具&#xff0c;真正用&#xff0c;查的过程才是学习的过程2.直接就上案例就行&#xff0c;先来跑&#xff0c;遇到什么来解决什么 Mnist分类任务&#xff1a; 网络基本构建与训练方法&#xff0c;常用函数解析…

【Linux命令详解 | cd命令】Linux系统中用于更改当前工作目录的命令

文章标题 简介一&#xff0c;参数列表二&#xff0c;使用介绍1. 使用cd命令切换到特定目录2. 使用cd命令与路径相关的特殊字符3. 使用cd命令切换到包含空格的目录4. 使用cd命令切换到前一个和后一个目录5. 使用cd命令切换到用户的主目录6. 使用cd命令与绝对路径和相对路径 总结…

【项目流程】前端项目的开发流程

1. 项目中涉及的所有角色及其职责 - PM 产品经理 产品经理&#xff08;Product Manager&#xff0c;简称PM&#xff09;负责明确和定义产品的愿景和战略&#xff0c;与客户、用户、业务部门和其他利益相关者进行沟通&#xff0c;收集并分析他们的需求和期望。负责制定产品的详…

TCP三次握手,四次挥手理解

1. 三次握手 *三次握手&#xff08;Three-way Handshake&#xff09;*其实就是指建立一个TCP连接时&#xff0c;需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备。实…

前端学习---vue2--选项/数据--data-computed-watch-methods-props

写在前面&#xff1a; vue提供了很多数据相关的。 文章目录 data 动态绑定介绍使用使用数据 computed 计算属性介绍基础使用计算属性缓存 vs 方法完整使用 watch 监听属性介绍使用 methodspropspropsData data 动态绑定 介绍 简单的说就是进行双向绑定的区域。 vue实例的数…

MPU6050

偏航角&#xff08;Yaw&#xff09; 横滚角&#xff08;ROll&#xff09; 俯仰角&#xff08;Pit&#xff09; 误差 mpu6050里面有一个受力的东西 受重力影响的电容 某个导体就往下一点 根据fma就可以算出当前的加速度值 加速度传感器只输出加速度 知道重力加速度和重力的角度可…

C++入门之stl六大组件--List源码深度剖析及模拟实现

文章目录 前言 一、List源码阅读 二、List常用接口模拟实现 1.定义一个list节点 2.实现一个迭代器 2.2const迭代器 3.定义一个链表&#xff0c;以及实现链表的常用接口 三、List和Vector 总结 前言 本文中出现的模拟实现经过本地vs测试无误&#xff0c;文件已上传gite…

java: 非法字符: ‘\ufeff‘

遇到这种情况是编码转换问题 解决办法&#xff1a; 单个文件&#xff1a;可以先将格式转换为utf-16&#xff0c;然后在转换回utf-8 多个文件&#xff1a;在setting-file encodings将乱码的这个文件夹里的所有Java文件都设置utf-8格式就可以了

小成本大幅度增幅CNN鲁棒性,完美的结合GLCM+CNN

本文以实验为导向&#xff0c;使用vgg16GLCM实现一场精彩的新冠肺炎的分类识别&#xff0c;并且对比不加GLCM后的效果。在这之前&#xff0c;我们需要弄明白一些前缀知识和概念问题&#xff1a; GLCM&#xff08;Gray-Level Co-occurrence Matrix&#xff09;&#xff0c;中文称…

比特鹏哥-数据类型和变量【自用笔记】

这里写目录标题 1.数据类型介绍字符&#xff0c;整型&#xff0c;浮点型&#xff0c;布尔类型 2.signed 和unsigned3.数据类型的取值范围sizeof 展示字节大小--- 计算机中单位&#xff1a;字节 4.变量 常量4.1 变量创建变量&#xff08;数据类型 变量名&#xff09;创建变量的时…

基于react-native的简单消息确认框showModel

基于react-native的简单消息确认框showModel 效果示例图组件代码ShowModel/index.jsx使用案例device.js安装线性渐变色 效果示例图 组件代码ShowModel/index.jsx import React, {forwardRef, useImperativeHandle, useState} from react; import {View,Text,Modal,TouchableOp…

2023,哪些大厂不再值钱?

2023年&#xff0c;摘下口罩的第一年&#xff0c;虽然经济复苏没那么强劲&#xff0c;但对于在资本寒冬中熬了许久的互联网科技股来说&#xff0c;春天的步伐好像越来越近了。今年以来&#xff0c;主要互联网科技公司的股价基本都涨了不少&#xff0c;尤其美国那边&#xff0c;…