cuda编程之一——初识CUDA


cuda编程——初识CUDA

对于CUDA编程,想必熟悉深度学习的同学大多对此都有一些了解,但是对于进一的探讨可能就涉及到一些知识的盲区了,因此本专栏尝试对这部分的内容进行相关探讨,学习过程中难免出现错误,还望各位大佬在理解的同时不吝赐教,在评论区留下你的看法,小万在此谢过了~ 对于任何知识,我觉得应该都从那个著名的Golden Circle的三个维度进行学习,才能对相关知识有一个更好的理解。因此,对于CUDA编程我们也从这三个角度进行阐述,本篇内容介绍WHY和WHAT,让大家对此有个初步了解,从第二篇博文开始介绍详细的CUDA编程方法论(当然其中的每一篇方法论又可以更细致的从WHW的三个维度进行理解)。 好了,我们闲言少叙,正式开始今天的内容学习:

1、WHY GPU&CUDA

说到CUDA编程,这里我们就不得不提到这个对于深度学习至关重要的运算设备GPU(Graphics Processing Unit)图形处理单元。 在此我们对GPU的发展历程进行相关梳理,以便大家对其有一个更深刻的认识。 谈到GPU,可能对于熟悉深度学习的各位来说,第一时间理解的都是关于深度学习的,其次就是游戏相关的。没错其实对于游戏场景等的图形图像渲染才是GPU提出的初衷。下面是GPT-4帮我生成的一份大致GPU发展历程,不一定全对,但可供大家进行参考: history of gpu history of cuda

从上述GPU的发展历程我们可以看出: 1、GPU的提出是为了对3D等图形图像进行渲染。 2、由于GPU为了进行图形图像渲染,使其具备了更强大的并行计算能力。这就使得当时的一些研究人员尝试使用GPU进行一些并行计算。 3、NVIDIA也看到了GPU在科学计算方面的能力,因此其为此设计了一个专门的解决方案,即CUDA(Compute Unified Device Architecture),这使得研究人员可以用C等高级语言直接对GPU进行编程,使研究人员可以针对自己的研究领域和计算需求个性化的使用GPU进行科学计算。

说到这里相信大家对于CUDA的诞生有了一定的了解了。接下来我们进一步对CUDA进行一个概览。

2、WHAT GPU&CUDA

GPU和CPU对比,GPU将更多晶体管用于数据处理

GPU

GPU谈到GPU这里我们就不得不提一字母之差的CPU。从上图我们可以看出GPU相比于CPU,缓存结构和控制流更少,将更多的处理器用于了数据处理,这也使得其具备更强大的数据计算能力。 我们可以这样简单的理解:单论单处理器的能力而言CPU无疑是更强大的,但作为整台电脑的核心,CPU的职责注定其不能将全部的重心用于数据处理这样单一的任务,它需要操心的事太多了,更何况,如果把CPU的核心数换成与GPU相同,那种CPU的价格将是不可接受的。 因此,GPU被研发出来了,更具性价比、功能性更好的处理单元。 这就好比导师和你的关系,在学习能力和专业建树上无疑是导师更强大,但因为导师需要统筹全实验室的发展,不能陷入到一些繁杂重复的任务中去,这时候我们学生的优势就来了,年轻有活力,这些繁杂重复的工作自然就落到我们头上了。这么看来,其实也不仅仅是在实验室,全社会好像都是这种分工。不多说了,再说就要聊到哲学了。

接下来我们看看官方文档对GPU的特性是怎么介绍的吧:

Devoting more transistors to data processing, for example, floating-point computations, is beneficial for highly parallel computations; the GPU can hide memory access latencies with computation, instead of relying on large data caches and complex flow control to avoid long memory access latencies, both of which are expensive in terms of transistors. In general, an application has a mix of parallel parts and sequential parts, so systems are designed with a mix of GPUs and CPUs in order to maximize overall performance. Applications with a high degree of parallelism can exploit this massively parallel nature of the GPU to achieve higher performance than on the CPU. 翻译一下: GPU将更多的处理器集体管用于数据处理,例如浮点计算,有利于高度并行计算; GPU可以通过计算来隐藏内存访问延迟,而不是依赖大数据缓存和复杂的流程控制来避免较长的内存访问延迟,而这两者对于晶体管而言都是昂贵的。 一般来说,应用程序混合有并行部分和顺序部分,因此系统设计时混合使用 GPU 和 CPU,以最大限度地提高整体性能。 具有高度并行性的应用程序可以利用 GPU 的大规模并行特性来实现比 CPU 更高的性能。

我们前面提到过GPU的缓存和流程控制单元较少,这也就使得其这两种能力较弱。而这在数据处理过程中可能会引发内存访问的延迟,因此GPU进行了相关的设计以及其自身具备的并行计算能力来对内存访问延迟进行隐藏,这也就是我们在接下来学习中会遇到的延迟隐藏。同时纹理内存等专用缓存的设计也会减弱内存访问延迟的影响,提高GPU的数据处理能力和效率。

CUDA

官方介绍: 2006 年 11 月,NVIDIA® 推出了 CUDA®,这是一种通用并行计算平台和编程模型,它利用 NVIDIA GPU 中的并行计算引擎以比 CPU 更高效的方式解决许多复杂的计算问题。 CUDA 附带一个软件环境,允许开发人员使用 C++ 作为高级编程语言。 支持其他语言、应用程序编程接口或基于指令的方法,例如 FORTRAN、DirectCompute、OpenACC。

从上述介绍中我们知道了GPU确实具备很强的计算能力,但是科学研究和密集型计算任务种类多种多样,需求各不相同,要想最大程度的利用好GPU,我们还需要一套工具个性化的对GPU进行操作,以适配研究人员的需求。 这也就催生了CUDA,这就使我们可以使用C++等语言开发出最大程度上利用GPU并行计算能力的程序。

CUDA编程模型将其核心概念抽象为三个层次结构:a hierarchy of thread groups(并行线程组), shared memories(共享内存), and barrier synchronization(屏障同步)。 通过这三个抽象的层次结构,我们可以将粗粒度的并行数据和并行任务进行细粒度的划分。即将原始问题划分为可以由线程块并行解决的粗略子问题,并将每个粗略子问题进一步划分为可以有块内所有线程并行解决的更细分的问题。 动态线程调度

作为CUDA上执行计算的基本单元,我们每一次的计算任务都是落到线程的头上,CUDA中对待线程也给予了极大地权限:每个线程块都可以以任何顺序(同时或顺序)调度到 GPU 内的任何可用多处理器上,以便编译后的 CUDA 程序可以在任意数量的多处理器上执行。 这意味着线程被组织成线程块和网格之后可以在GPU的流处理器(Streaming Multi-Processors)上动态的调度执行,无论GPU上有多少个流处理器(SMs),CUDA程序都能有效的利用这些硬件资源。

总结

  1. GPU最初用来进行图像渲染,其具备的并行能力被研究人员尝试用于科学计算。
  2. NVIDIA为便于研究人员更好的应用GPU的并行计算能力,推出了CUDA编程模型。
  3. CUDA的核心概念是线程,每个计算任务最终落到线程上。
  4. GPU的核心是流处理器(Streaming Processor,SP),最终执行计算任务的硬件单元。
  5. 线程被组织成线程块或网格的形式运行在流多处理器上(Streaming Multi-Processors, SMs)。

今天的CUDA前瞻就分享这里,我是小万,Allen-wan,我们下期再见~

有任何疑问和建议欢迎在评论区留言~