CUDA刷新器:CUDA编程模型
CUDA刷新器:CUDA编程模型
CUDA Refresher: The CUDA Programming Model
CUDA,CUDA刷新器,并行编程
这是CUDA更新系列的第四篇文章,它的目标是刷新CUDA中的关键概念、工具和初级或中级开发人员的优化。
CUDA编程模型提供了GPU体系结构的抽象,它充当了应用程序与其在GPU硬件上的可能实现之间的桥梁。这篇文章概述了CUDA编程模型的主要概念,概述了它如何在通用编程语言如C/C++中暴露出来。
介绍一下CUDA编程模型中常用的两个关键词:主机和设备。
主机是系统中可用的CPU。与CPU相关联的系统内存称为主机内存。GPU被称为设备,GPU内存也被称为设备内存。
要执行任何CUDA程序,有三个主要步骤:
将输入数据从主机内存复制到设备内存,也称为主机到设备传输。
加载GPU程序并执行,在片上缓存数据以提高性能。
将结果从设备内存复制到主机内存,也称为设备到主机传输。
CUDA内核和线程层次结构
图1显示了CUDA内核是一个在GPU上执行的函数。应用程序的并行部分由K个不同的CUDA线程并行执行k次,而不是像常规C/C++函数那样只进行一次。
Figure 1. The kernel is a function executed on the GPU.
每一个CUDA内核都以一个__global__声明说明符开头。程序员通过使用内置变量为每个线程提供唯一的全局ID。
图2. CUDA内核被细分为块。
一组线程称为CUDA块。CUDA块被分组到一个网格中。内核作为线程块的网格来执行(图2)。
每个CUDA块由一个流式多处理器(SM)执行,不能迁移到GPU中的其他SMs(抢占、调试或CUDA动态并行期间除外)。一个SM可以根据CUDA块所需的资源运行多个并发CUDA块。每个内核在一个设备上执行,CUDA支持一次在一个设备上运行多个内核。图3显示了GPU中可用硬件资源的内核执行和映射。
图3. 在GPU上执行内核。
CUDA为线程和块定义了内置的三维变量。线程使用内置的三维变量threadIdx编制索引。三维索引提供了一种自然的方法来索引向量、矩阵和体积中的元素,并使CUDA编程更容易。类似地,块也使用名为blockIdx的内置三维变量编制索引。
以下是几个值得注意的要点:
CUDA架构限制每个块的线程数(每个块限制1024个线程)。
线程块的维度可以通过内置的blockDim变量在内核中访问。
syncu中的线程可以使用syncu函数同步。使用同步线程时,块中的所有线程都必须等待,然后才能继续。
在<<…>>>语法中指定的每个块的线程数和每个网格的块数可以是int或dim3类型。这些三角括号标记从主机代码到设备代码的调用。它也被称为内核启动。
下面用于添加两个矩阵的CUDA程序显示多维blockIdx和threadIdx以及blockDim等其他变量。在下面的例子中,为了便于索引,选择了一个2D块,每个块有256个线程,x和y方向各有16个线程。使用数据大小除以每个块的大小来计算块的总数。
// Kernel - Adding two matrices MatA and MatB
__global__ void MatAdd(float MatA[N][N], float MatB[N][N],
float MatC[N][N])
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
int j = blockIdx.y * blockDim.y + threadIdx.y;
if (i < N && j < N)
MatC[i][j] = MatA[i][j] + MatB[i][j];
}
int main()
{
...
// Matrix addition kernel launch from host code
dim3 threadsPerBlock(16, 16);
dim3 numBlocks((N + threadsPerBlock.x -1) / threadsPerBlock.x, (N+threadsPerBlock.y -1) / threadsPerBlock.y);
MatAdd<<<numBlocks, threadsPerBlock>>>(MatA, MatB, MatC);
...
}
Memory hierarchy
支持CUDA的GPU有一个内存层次结构,如图4所示。
图4. gpu中的内存层次结构。
以下内存由GPU架构公开:
这些寄存器对每个线程都是私有的,这意味着分配给线程的寄存器对其他线程不可见。编译器决定寄存器的利用率。
一级/共享内存(SMEM)-每个SM都有一个快速的片上草稿行内存,可用作一级缓存和共享内存。CUDA块中的所有线程都可以共享共享内存,在给定SM上运行的所有CUDA块都可以共享SM提供的物理内存资源。。
只读内存每个SM都有一个指令缓存、常量内存、纹理内存和对内核代码只读的RO缓存。
二级缓存二级缓存在所有SMs中共享,因此每个CUDA块中的每个线程都可以访问该内存。nvidiaa100 GPU已经将二级缓存大小增加到40mb,而v100gpu中只有6mb。
全局内存这是位于GPU中的GPU和DRAM的帧缓冲区大小。
NVIDIA CUDA编译器在优化内存资源方面做得很好,但专家CUDA开发人员可以选择有效地使用这种内存层次结构来优化CUDA程序。
计算能力
GPU的计算能力决定了GPU硬件支持的通用规范和可用特性。此版本号可由应用程序在运行时使用,以确定当前GPU上可用的硬件功能或指令。
每个GPU都有一个版本号,表示为X.Y,其中X包括主要修订号,Y包含次要修订号。小版本号对应于架构的增量改进,可能包括新特性。
有关任何支持CUDA的设备的计算能力的更多信息,请参阅CUDA示例代码设备查询。此示例枚举系统中存在的CUDA设备的属性。
摘要
CUDA编程模型提供了一种异构环境,其中主机代码在CPU上运行C/C++程序,内核在物理上分离的GPU设备上运行。CUDA编程模型还假设主机和设备都保持各自独立的内存空间,分别称为主机内存和设备内存。CUDA代码还通过PCIe总线提供主机和设备内存之间的数据传输。
CUDA还公开了许多内置变量,并提供了多维索引的灵活性,以简化编程。CUDA还管理不同的内存,包括寄存器、共享内存和一级缓存、二级缓存和全局内存。高级开发人员可以有效地使用这些内存来优化CUDA程序。
CUDA刷新器:CUDA编程模型的更多相关文章
- CUDA编程模型
1. 典型的CUDA编程包括五个步骤: 分配GPU内存 从CPU内存中拷贝数据到GPU内存中 调用CUDA内核函数来完成指定的任务 将数据从GPU内存中拷贝回CPU内存中 释放GPU内存 *2. 数据 ...
- CUDA编程模型之内存管理
CUDA编程模型假设系统是由一个主机和一个设备组成的,而且各自拥有独立的内存. 主机:CPU及其内存(主机内存),主机内存中的变量名以h_为前缀,主机代码按照ANSI C标准进行编写 设备:GPU及其 ...
- CUDA刷新:GPU计算生态系统
CUDA刷新:GPU计算生态系统 CUDA Refresher: The GPU Computing Ecosystem 这是CUDA Refresher系列的第三篇文章,其目标是刷新CUDA中的关键 ...
- 【并行计算-CUDA开发】CUDA存储器模型
CUDA存储器模型 除了执行模型以外,CUDA也规定了存储器模型(如图2所示)和一系列用于主控CPU与GPU间通信的不同地址空间.图中红色的区域表示GPU片内的高速存储器,橙色区域表示DRAM中的的地 ...
- CUDA 8混合精度编程
CUDA 8混合精度编程 Mixed-Precision Programming with CUDA 8 论文地址:https://devblogs.nvidia.com/mixed-precisio ...
- 第3章 窗口与消息_3.1Windows编程模型
第3章窗口与消息 3.1 Windows_编程模型 (1)窗口程序的运行过程 ①设计窗口 ②注册窗口类(RegisterClassEx).在注册之前,要先填写RegisterClassEx的参 ...
- 并行计算基础&编程模型与工具
在当前计算机应用中,对快速并行计算的需求是广泛的,归纳起来,主要有三种类型的应用需求: 计算密集(Computer-Intensive)型应用,如大型科学project计算与数值模拟: 数据密集(Da ...
- 老李分享: 并行计算基础&编程模型与工具 2
2.并行编程模型和工具 – MPI – MPI(Message Passing Interface)是一种消息传递编程模型,服务于进程通信.它不特指某一个对它的实现,而是一种标准和规范的代表,它是一种 ...
- 老李分享: 并行计算基础&编程模型与工具
在当前计算机应用中,对高速并行计算的需求是广泛的,归纳起来,主要有三种类型的应用需求: 计算密集(Computer-Intensive)型应用,如大型科学工程计算与数值模拟: 数据密集(Data-In ...
随机推荐
- locustfile中的User类和HttpUser类
locustfile是什么? locustfile是Locust性能测试工具的用户脚本,描述了单个用户的行为. locustfile是个普通的Python模块,如果写作locustfile.py,那么 ...
- .NET 平台系列6 .NET Core 发展历程
系列目录 [已更新最新开发文章,点击查看详细] 在我的上一篇博客<.NET平台系列5 .NET Core 简介>中主要介绍了.NETCore的基本情况,主要包括.NET跨平台的缘由 ...
- BD-rate的计算
相信不少接触视频编码的朋友在看相关的文献的时候,总会看到论文中测试时给出一个重要的参数BD-rate,可能一直心存疑问,这个BD-rate到底是个什么东西呢?可以参考这一份提案http://downl ...
- printf/scanf格式
(1)打印字符 char c; printf("%c",c); (2)打印整形 int i; printf("%d",i); //有符号十进制数 printf( ...
- OO_Unit1_表达式求导
CSDN链接 一.第一次作业 1.需求分析 简单多项式导函数 带符号整数 支持前导0的带符号整数,符号可省略,如: +02.-16.19260817等. 幂函数 一般形式 由自变量x和指数组成,指数为 ...
- [re模块、json&pickle模块]
[re模块.json&pickle模块] re模块 什么是正则? 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则 ...
- 浙江省第三届大学生网络与信息安全竞赛WP
title: 浙江省第三届大学生网络与信息安全预赛WP date: 2020-10-2 tags: CTF,比赛 categories: CTF 比赛 浙江省第三届大学生网络与信息安全竞赛WP 0x0 ...
- Linux 根目录所在分区被脏数据占满
背景: 公司在做一个项目,大概功能就是一个通行闸机的人脸识别系统,要经过门禁的人注册了之后,系统就会存储一张原始的图片在服务器的数据文件夹里面,包括了永久的存储和一些访客注册临时存储.一天周五的时 ...
- Linux_计划任务理论概述
一.计划任务概述 1.计划任务概述: 计划任务分为: 一次性任务 周期性任务 在Linux系统的计划任务服务crond 可以满足周期性执行任务的需求. crond进程每分钟会处璇一次计划任务,计划任务 ...
- Linux 操作系统(三) 添加用户、切换用户、删除用户
以下命令均已在 Kali Linux 验证. 1.添加用户 --1-- useradd -m username //username 代表你所添加的用户名 --2-- passw ...