CUDA学习笔记——CUDA简介
什么是 CUDA
有些文章说 CUDA 是一个库,或者是一个框架,都不是很准确。CUDA 其实是一个平台,一个提供通用并行计算和编程模型的平台。它利用底层 GPU 的多核并行计算引擎,通过提供丰富的接口和功能,来为应用层的并行计算开发带来便利。
CUDA 平台包括多种不同功能的组件:
- CUDA 加速库
- 编译器指令
- 应用程序接口
- 编程语言扩展(包括C、C++、Fortran、Python等)。
平时说的 CUDA 编程,就是指利用某个编程语言的扩展,比如 C 语言,以及 CUDA 提供的 运行时 API 等工具,来实现并行计算程序开发。
CUDA API
CUDA 提供了多种编程语言的扩展,其中使用最多的就是 CUDA C/C++。CUDA C 是对标准 ANSI C 的扩展,使用扩展语法,以及一些 API,就可以直接操控 GPU 设备、GPU 内存从而在 GPU 上执行任务。
CUDA 提供了一种可伸缩的编程模型,当 GPU 硬件的性能无法胜任一个程序时,只需简单地增加 SM 和核数等硬件配置,而无需大量地改动程序本身。
CUDA 提供了两种层次的 API:
- CUDA 驱动 API
- CUDA 运行时 API
CUDA 驱动 API 是一个更底层的 API 接口,偏硬件,相对比较难上手,但使用它可以更精细地控制 GPU 设备。
运行时 API 是基于 驱动 API 做了封装,更符合程序员惯有的思维模式,所以上手更快。
从性能角度来说,两种 API 没有太大的区别,你写的并行程序能否满足性能需求,更多地是取决于你程序中的线程、线程块、内存是如何组织的,而不是用哪种 API。
两种 API 是互斥的,一般不能混合使用。
CUDA 程序结构
一个 CUDA C 程序通常包含两部分:
- 运行在 CPU 上的 host code
- 运行在 GPU 上的 device code
Nvidia 的 CUDA nvcc 编译器在编译程序时,会把 host code 和 device code 分开。
host code,是用标准 C 写的,nvcc 会用内嵌的 C 编译器去编译成符合 CPU 结构的机器码。
device code, 是用 CUDA C 的扩展的符号和语法写的函数,这类函数称为 kernel,nvcc 将它们编译为 GPU 指令。
在链接时,除了上述两部分代码,CUDA 运行时库也会被链接进来,最终生成一个可执行程序。
CUDA 程序做的事情大致上可以分为这几个部分:
- 分配 GPU 内存;
- 将相关数据从 CPU 内存拷贝到 GPU 内存;
- 调用 CUDA kernel 来运行指定的计算;
- 将计算结果从 GPU 内存拷贝到 CPU 内存;
- 回收 GPU 内存。
CUDA 编程和传统编程的差异
在学习 CUDA 编程的过程中,我感受到它和传统编程最大的差异在于:你需要对 GPU 架构有一定的了解。
传统编程都是在 CPU 上跑的,而现代主流编程语言把计算机底层的工作模式都变成透明的了,意味着程序员只需要了解编程语言的语法,大部分时候无需关注和了解程序的运行方式。虽然计算机科班的童鞋在大学里必修计算机体系结构等偏底层的课程,但毕业后的工作中,又有多少内容和这有关呢?
比如,我们大学里一定学过多发射、流水线、指令级并行、SIMD、cache line、全相联/组相联/直接映射、虚拟存储、缺页等概念,但我敢说,在大部分技术工作中,你几乎不会和这些东西打交道。因为高级编程语言,把这些东西隐藏了起来。
但如果你要开发跑在 GPU 上的程序,情况就不同了。你如果想让你的程序高效一点,就需要了解 GPU 架构。有时候,仅仅一个细微的改变,比如将线程块的维度更改一下,程序的性能马上就能上一个数量级。
这种知识细节和产出效益仅仅关联的模式,大概就是学习 GPU CUDA 编程的最大乐趣吧!
「 您的赞赏是激励我创作和分享的最大动力! 」
- 原文链接:https://zhuyinjun.me/2021/cuda_learning_3/
- 版权声明:本创作采用 CC BY-NC 4.0 国际许可协议,非商业性使用可以转载,但请注明出处(作者、链接),商业性使用请联系作者获得授权。