CUDA从入门到放弃(四):CUDA 编程模式 CUDA Programming Model

news2024/11/24 22:37:06

CUDA从入门到放弃(四):CUDA 编程模式 CUDA Programming Model

1 Kernels

CUDA C++ 扩展了 C++,允许定义名为内核的函数,这些函数可以被不同的 CUDA 线程并行执行多次,而不是像普通 C++ 函数那样只执行一次。内核通过 global 声明符定义,执行内核的 CUDA 线程数通过特殊的执行配置语法指定。每个执行内核的线程都有一个唯一的线程 ID,可在内核内部通过内置变量获取。

// Kernel definition
__global__ void VecAdd(float* A, float* B, float* C)
{
    int i = threadIdx.x;
    C[i] = A[i] + B[i];
}
int main()
{
    ...
        ∕∕ Kernel invocation with N threads
        VecAdd << <1, N >> > (A, B, C);
    ...
}

2 Thread Hierarchy 线程结构

为了方便起见,threadIdx 是一个三分量向量,因此可以使用一维、二维或三维线程索引来识别线程,形成一个一维、二维或三维的线程块,称为线程块。

每个线程块内的线程数有上限,因为所有线程需共享同一流式多处理器核心的有限内存资源。目前GPU上,线程块最多包含1024个线程。 尽管如此,一个内核可以由多个相同形状的线程块执行,总线程数等于每个块的线程数乘以块的数量。
在这里插入图片描述

线程块组织成一维、二维或三维网格,由数据大小决定,通常超出系统处理器数量。在执行配置语法中指定的线程数和块数可以是int或dim3类型。每个块通过内置的blockIdx变量在内核中按唯一索引识别,线程块维度通过内置的blockDim变量获取。

∕∕ Kernel definition
__global__ void MatAdd(float A[N][N], float B[N][N], float C[N][N])
{
	int i = blockIdx.x * blockDim.x + threadIdx.x;
	int j = blockIdx.y * blockDim.y + threadIdx.y;
	if (i < N && j < N)
	C[i][j] = A[i][j] + B[i][j];
}
int main()
{
	...
	∕∕ Kernel invocation
	dim3 threadsPerBlock(16, 16);
	dim3 numBlocks(N ∕ threadsPerBlock.x, N ∕ threadsPerBlock.y);
	MatAdd<<<numBlocks, threadsPerBlock>>>(A, B, C);
	...
}

线程块需能独立执行,可任意顺序并行或串行执行。这允许在多个核心上灵活调度线程块,使代码能随核心数扩展。

块内线程通过共享内存和执行同步来协作,使用__syncthreads()函数设置同步点,作为所有线程必须等待的屏障。共享内存应为低延迟内存,类似于L1缓存,且__syncthreads()操作应轻量级。

2-1 Thread Block Clusters 线程块集群

NVIDIA计算能力9.0引入了一个新的层级结构——线程块集群,由线程块组成。线程块集群中的线程块保证在GPU的处理集群上共同调度。集群可以是一维、二维或三维结构,用户可自定义集群中的线程块数量,CUDA中推荐的最大集群大小为8个线程块。对于小于8个多处理器的GPU硬件或MIG配置,最大集群大小会相应减少。可以通过cudaOccupancyMaxPotentialClusterSize API查询特定架构支持的集群大小。
在这里插入图片描述
线程块集群可以在内核中通过使用编译时内核属性 cluster_dims(X,Y,Z) 或者使用CUDA内核启动API cudaLaunchKernelEx 来启用。

2-1-1 编译时内核属性启动集群

使用内核属性的集群大小在编译时固定,然后可以使用传统的 <<< , >>> 语法启动内核。如果一个内核使用了编译时集群大小,那么在启动内核时不能修改集群大小。

∕∕ Kernel definition
∕∕ Compile time cluster size 2 in X-dimension and 1 in Y and Z dimension
__global__ void __cluster_dims__(2, 1, 1) cluster_kernel(float *input, float* output)
{ }
int main()
{
	float *input, *output;
	∕∕ Kernel invocation with compile time cluster size
	dim3 threadsPerBlock(16, 16);
	dim3 numBlocks(N ∕ threadsPerBlock.x, N ∕ threadsPerBlock.y);
	∕∕ The grid dimension is not affected by cluster launch, and is still enumerated
	∕∕ using number of blocks.
	∕∕ The grid dimension must be a multiple of cluster size.
	cluster_kernel<<<numBlocks, threadsPerBlock>>>(input, output);
}
2-1-2 cudaLaunchKernelEx 来启动内核

使用CUDA内核启动API cudaLaunchKernelEx 来启动内核

∕∕ Kernel definition
∕∕ No compile time attribute attached to the kernel
__global__ void cluster_kernel(float *input, float* output)
{ }
int main()
{
	float *input, *output;
	dim3 threadsPerBlock(16, 16);
	dim3 numBlocks(N ∕ threadsPerBlock.x, N ∕ threadsPerBlock.y);
	∕∕ Kernel invocation with runtime cluster size
	{
		cudaLaunchConfig_t config = {0};
		∕∕ The grid dimension is not affected by cluster launch, and is still enumerated
		∕∕ using number of blocks.
		∕∕ The grid dimension should be a multiple of cluster size.
		config.gridDim = numBlocks;
		config.blockDim = threadsPerBlock;
		cudaLaunchAttribute attribute[1];
		attribute[0].id = cudaLaunchAttributeClusterDimension;
		attribute[0].val.clusterDim.x = 2; ∕∕ Cluster size in X-dimension
		attribute[0].val.clusterDim.y = 1;
		attribute[0].val.clusterDim.z = 1;
		config.attrs = attribute;
		config.numAttrs = 1;
		cudaLaunchKernelEx(&config, cluster_kernel, input, output);
	}
}

3 Memory Hierarchy 内存结构

CUDA线程在执行过程中可能会访问多个内存空间。每个线程都有私有的本地内存。每个线程块都有共享内存,对块内的所有线程可见,并且与块的生命周期相同。线程块集群中的线程块可以对彼此的共享内存执行读、写和原子操作。所有线程都可以访问相同的全局内存。
在这里插入图片描述

4 Heterogeneous Programming

CUDA编程模型假定CUDA线程在物理上独立的设备上执行,作为运行C++程序的主机的协处理器,如GPU和CPU的组合使用。主机和设备各自维护独立的DRAM内存空间。程序通过CUDA运行时管理内核可见的内存空间,包括内存分配、释放和主机与设备间的数据传输。统一内存提供托管内存,实现主机与设备内存空间的统一管理,简化了应用程序的移植过程。
在这里插入图片描述

参考资料
1 CUDA编程入门
2 CUDA编程入门极简教程
3 CUDA C++ Programming Guide
4 CUDA C++ Best Practices Guide
5 NVIDIA CUDA初级教程视频
6 CUDA专家手册 [GPU编程权威指南]
7 CUDA并行程序设计:GPU编程指南
8 CUDA C编程权威指南

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

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

相关文章

【2024.3.26练习】画中漂流

题目描述 题目分析 根据题型分析应该可以用动态规划解决。设为第秒&#xff0c;剩余体力值为&#xff0c;且当前位置距离峡谷米时的总方案数。根据题意&#xff0c;状态转移方程如下&#xff1a; 这样定义状态的话空间复杂度为&#xff0c;大大超出了空间限制。观察转移方程左…

【SpringBoot】实现一个简单的图片上传

前端上传表单 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <form enctype"multipart/form-data" method"post" action&q…

拓展AI边界:去中心化人工智能的应用场景和主要项目盘点

随着区块链技术的发展和普及&#xff0c;去中心化人工智能&#xff08;AI&#xff09;逐渐成为技术领域的焦点之一。区块链的去中心化特性为AI技术的应用提供了新的可能性&#xff0c;使得数据共享、模型训练和应用部署更加安全、透明和可靠。本文将探索去中心化AI的应用场景&a…

【NLP学习记录】Embedding和EmbeddingBag

Embedding与EmbeddingBag详解 ●&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 ●&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 ●&#x1f680; 文章来源&#xff1a;K同学的学习圈子1、Embedding详解 Embedding是Pytorch中最基本…

Spring实例化Bean的三种方式

参考资料&#xff1a; Core Technologies 核心技术 spring实例化bean的三种方式 构造器来实例化bean 静态工厂方法实例化bean 非静态工厂方法实例化bean_spring中有参构造器实例化-CSDN博客 1. 构造函数 1.1. 空参构造函数 下面这样表示调用空参构造函数&#xff0c;使用p…

Mysql数据库函数【Mysql】

Mysql数据库函数【Mysql】 前言版权Mysql数据库函数常用函数排序与分页排序分页 单行函数2.数值函数2.1基本函数2.2角度与弧度2.3三角函数2.4指数与对数函数2.5进制间的转换 3.字符串函数4.日期和时间函数4.1获取日期、时间4.2日期与时间戳的转换4.3获取月份、星期、星期数、天…

C语言数据流讲解

目录 4.1 流&#xff08;Stream&#xff09;&#xff1a;数据流动的隐喻 4.1.1 流&#xff1a;数据传输的通用接口 4.1.2 标准流&#xff1a;预定义的流通道 4.2 文件指针&#xff1a;流操作的桥梁 4.2.1 文件指针的本质与结构 4.2.2 使用文件指针操作流 图解 结语 在C…

AI研报:从Sora看多模态大模型发展

《从Sora看多模态大模型发展》的研报来自浙商证券&#xff0c;写于2024年2月。 这篇报告主要探讨了多模态大模型的发展趋势&#xff0c;特别是OpenAI发布的视频生成模型Sora&#xff0c;以及其对行业发展的影响。以下是报告的核心内容概述&#xff1a; Sora模型的发布&#x…

错误 C2872 “byte”: 不明确的符号,在rpcndr.h或者objidl.h

主要问题出在这里面 #include “objbase.h” qtcreator 5.12 可以直接运行 vsqt2022 msvs2017就要报错 错误 C2872 “byte”: 不明确的符号 E:\GGtie\out\build\x64-debug\GGtie C:\Program Files (x86)\Windows Kits\10\include\10.0.22621.0\um\objidl.h 13832 解决方法…

网络七层模型之物理层:理解网络通信的架构(一)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

C++new与delete函数

CSDN成就一亿技术人 目录 C/C内存分布&#xff1a; 一.C内存管理方式 1.new/delete操作内置类型 2.new和delete操作自定义类型 二.operato new与operator delete函数 1.operator new与operator delete函数 三.new和delete的实现原理 1.内置类型 2.自定义类型 四…

openssl 升级1.1.1.1k 到 3.0.13

下载 https://www.openssl.org/source/ tar -zxvf openssl-3.0.13.tar.gzcd openssl-3.0.13/./config enable-fips --prefix/usr/local --openssldir/usr/local/opensslmake && make install 将原有openssl备份 mv /usr/bin/openssl /usr/bin/openssl.bak mv /usr/i…

基于springboot实现房产销售系统项目【项目源码+论文说明】

基于springboot实现房产销售系统演示 摘要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于房产销售系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了房产销售系统…

水工电缆线施工注意事项及检验要求

水工电缆线施工是一个涉及多个环节的复杂过程&#xff0c;对施工质量、严密度、工作效率的要求都较为严格。以下是一些关键的注意事项及检验要求&#xff1a; 注意事项&#xff1a; 电缆敷设时&#xff0c;应从盘的上端引出&#xff0c;避免在支架上及地面摩擦拖拉&#xff0c;…

虚拟 DOM 的优缺点有哪些

虚拟DOM&#xff08;Virtual DOM&#xff09;技术作为现代前端开发中的重要组成部分&#xff0c;已经成为了众多流行前端框架的核心特性。它的引入为前端开发带来了诸多优势&#xff0c;同时也需要我们认真思考其潜在的考量。下面简单的介绍一下虚拟DOM技术的优势与缺点&#x…

ASR-LLM-TTS 大模型对话实现案例;语音识别、大模型对话、声音生成

参考:https://blog.csdn.net/weixin_42357472/article/details/136305123(llm+tts) https://blog.csdn.net/weixin_42357472/article/details/136411769 (asr+vad) 这里LLM用的是chatglm;电脑声音播报用的playsound 代码: ##运行 python main.pymain.py from multipro…

npm ERR! cb() never called!(已解决)

从仓库拉下来的代码&#xff0c;用npm install时报错 试了很多种方法&#xff0c;结果发现有一种可能是你的node版本过低导致的&#xff0c;可以升级node版本试一下。 node版本升级后&#xff0c;把上一次npm install错误的node_modules删除&#xff0c;重新npm install。

线上问题排查实例分析|Redis使用不同编码引发的问题

前言 某个周末的晚上突然收到一波耗时上升报警&#xff0c;仔细一看报警消息&#xff0c;原来是出现了慢查请求导致集群耗时大幅上升&#xff0c;此时业务同学也收到上游服务受影响报警。在处理问题过程中&#xff0c;运维同学发现 Redis 集群中只有部分实例出现 cpu 利用率上…

【Rust】——提取函数消除重复代码和泛型

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

手机和键盘的数字键盘排序为什么是不同的?

不知道你有没有注意有一个问题。我们的手机输入法中的数字键盘&#xff0c;电脑上通用的数字键盘&#xff0c;计算器上的数字键盘等排序是不同的&#xff0c;从观察者角度看&#xff0c;0-9的数字排列有从上到下的排列&#xff0c;还有从下到上的排列。为什么会出现不同的排列方…