热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

cuda编程_CUDA刷新器:CUDA编程模型

CUDA刷新器:CUDA编程模型CUDARefresher:TheCUDAProgrammingModelCUDA,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++函数那样只进行一次。

8e23a178377a9e324e641dcb844292b1.png

Figure 1. The kernel is a function executed on the GPU.

每一个CUDA内核都以一个__global__声明说明符开头。程序员通过使用内置变量为每个线程提供唯一的全局ID。

a0904a348645f2e04f64e8f970252055.png

图2. CUDA内核被细分为块。

一组线程称为CUDA块。CUDA块被分组到一个网格中。内核作为线程块的网格来执行(图2)。

每个CUDA块由一个流式多处理器(SM)执行,不能迁移到GPU中的其他SMs(抢占、调试或CUDA动态并行期间除外)。一个SM可以根据CUDA块所需的资源运行多个并发CUDA块。每个内核在一个设备上执行,CUDA支持一次在一个设备上运行多个内核。图3显示了GPU中可用硬件资源的内核执行和映射。

403e925b8fb639ed59741a7d89331f3a.png

图3. 在GPU上执行内核。

CUDA为线程和块定义了内置的三维变量。线程使用内置的三维变量threadIdx编制索引。三维索引提供了一种自然的方法来索引向量、矩阵和体积中的元素,并使CUDA编程更容易。类似地,块也使用名为blockIdx的内置三维变量编制索引。

以下是几个值得注意的要点:

CUDA架构限制每个块的线程数(每个块限制1024个线程)。

线程块的维度可以通过内置的blockDim变量在内核中访问。

syncu中的线程可以使用syncu函数同步。使用同步线程时,块中的所有线程都必须等待,然后才能继续。

在<<…>>>语法中指定的每个块的线程数和每个网格的块数可以是int或dim3类型。这些三角括号标记从主机代码到设备代码的调用。它也被称为内核启动。

下面用于添加两个矩阵的CUDA程序显示多维blockIdx和threadIdx以及blockDim等其他变量。在下面的例子中&#xff0c;为了便于索引&#xff0c;选择了一个2D块&#xff0c;每个块有256个线程&#xff0c;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 &#61; blockIdx.x * blockDim.x &#43; threadIdx.x; int j &#61; blockIdx.y * blockDim.y &#43; threadIdx.y; if (i MatC[i][j] &#61; MatA[i][j] &#43; MatB[i][j];}int main(){ ... // Matrix addition kernel launch from host code dim3 threadsPerBlock(16, 16); dim3 numBlocks((N &#43; threadsPerBlock.x -1) / threadsPerBlock.x, (N&#43;threadsPerBlock.y -1) / threadsPerBlock.y); MatAdd<<>>(MatA, MatB, MatC); ...}
Memory hierarchy

支持CUDA的GPU有一个内存层次结构&#xff0c;如图4所示。

e709a10bde7b3728e9d7f0bb14a3eefa.png

图4. gpu中的内存层次结构。

以下内存由GPU架构公开&#xff1a;

这些寄存器对每个线程都是私有的&#xff0c;这意味着分配给线程的寄存器对其他线程不可见。编译器决定寄存器的利用率。

一级/共享内存&#xff08;SMEM&#xff09;-每个SM都有一个快速的片上草稿行内存&#xff0c;可用作一级缓存和共享内存。CUDA块中的所有线程都可以共享共享内存&#xff0c;在给定SM上运行的所有CUDA块都可以共享SM提供的物理内存资源。。

只读内存每个SM都有一个指令缓存、常量内存、纹理内存和对内核代码只读的RO缓存。 二级缓存二级缓存在所有SMs中共享&#xff0c;因此每个CUDA块中的每个线程都可以访问该内存。nvidiaa100 GPU已经将二级缓存大小增加到40mb&#xff0c;而v100gpu中只有6mb。 全局内存这是位于GPU中的GPU和DRAM的帧缓冲区大小。

NVIDIA CUDA编译器在优化内存资源方面做得很好&#xff0c;但专家CUDA开发人员可以选择有效地使用这种内存层次结构来优化CUDA程序。

计算能力

GPU的计算能力决定了GPU硬件支持的通用规范和可用特性。此版本号可由应用程序在运行时使用&#xff0c;以确定当前GPU上可用的硬件功能或指令。

每个GPU都有一个版本号&#xff0c;表示为X.Y&#xff0c;其中X包括主要修订号&#xff0c;Y包含次要修订号。小版本号对应于架构的增量改进&#xff0c;可能包括新特性。

有关任何支持CUDA的设备的计算能力的更多信息&#xff0c;请参阅CUDA示例代码设备查询。此示例枚举系统中存在的CUDA设备的属性

摘要

CUDA编程模型提供了一种异构环境&#xff0c;其中主机代码在CPU上运行C/C&#43;&#43;程序&#xff0c;内核在物理上分离的GPU设备上运行。CUDA编程模型还假设主机和设备都保持各自独立的内存空间&#xff0c;分别称为主机内存和设备内存。CUDA代码还通过PCIe总线提供主机和设备内存之间的数据传输。

CUDA还公开了许多内置变量&#xff0c;并提供了多维索引的灵活性&#xff0c;以简化编程。CUDA还管理不同的内存&#xff0c;包括寄存器、共享内存和一级缓存、二级缓存和全局内存。高级开发人员可以有效地使用这些内存来优化CUDA程序。



推荐阅读
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • C++中的三角函数计算及其应用
    本文介绍了C++中的三角函数的计算方法和应用,包括计算余弦、正弦、正切值以及反三角函数求对应的弧度制角度的示例代码。代码中使用了C++的数学库和命名空间,通过赋值和输出语句实现了三角函数的计算和结果显示。通过学习本文,读者可以了解到C++中三角函数的基本用法和应用场景。 ... [详细]
  • 本文介绍了在多平台下进行条件编译的必要性,以及具体的实现方法。通过示例代码展示了如何使用条件编译来实现不同平台的功能。最后总结了只要接口相同,不同平台下的编译运行结果也会相同。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了C函数ispunct()的用法及示例代码。ispunct()函数用于检查传递的字符是否是标点符号,如果是标点符号则返回非零值,否则返回零。示例代码演示了如何使用ispunct()函数来判断字符是否为标点符号。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有