一、GPU计算概述:从CPU到GPU的演进

1.1 为什么我们需要GPU?

说实话,我刚入行那会儿,也觉得CPU挺全能的。什么活儿都能干,多好。但后来发现,有些任务——比如渲染一张4K图片、训练一个神经网络——CPU跑起来就像老牛拉车。

为什么会这样?

CPU的设计哲学是「单核性能至上」。它把大量晶体管花在缓存、分支预测、乱序执行上。说白了,CPU是个全能冠军,但一次只能处理几个任务。

GPU不一样。它把晶体管几乎全堆在计算单元上。一个GPU有几千个核心,虽然每个核心很弱,但架不住人多。你想想看,一个CPU有8个核,一个GPU有5000个核,谁更适合并行计算?

核心区别一句话:CPU是法拉利,跑得快但只能拉一个人;GPU是公交车,跑得慢但能拉一车人。

1.2 GPU的架构特点:SIMT

GPU最核心的概念,就是SIMT——单指令多线程。我当年第一次接触这个,觉得这名字起得真绕。说白了就是:一个指令,让一堆线程同时执行

举个例子。你要给一万个像素调亮度。CPU的做法:循环一万次,每次处理一个像素。GPU的做法:启动一万个线程,每个线程处理一个像素,所有线程同时跑。

嗯,这里要注意:SIMT和SIMD(单指令多数据)不一样。SIMD要求数据必须对齐,必须连续。SIMT灵活得多,每个线程可以有自己的寄存器、自己的内存地址。我在项目中遇到过,用SIMD写图像处理,数据对齐搞到头秃。换成SIMT,舒服多了。

GPU内部的组织结构是这样的:

GPU
├── 流多处理器 (SM) × N
│   ├── CUDA核心 × M
│   ├── 共享内存
│   ├── 寄存器文件
│   └── 线程调度器
├── 全局内存 (显存)
├── L2缓存
└── 内存控制器

每个SM(流多处理器)里有一堆CUDA核心。线程以32个为一组,叫做一个warp。warp里的线程必须执行同一条指令。如果线程分支了?那就会串行执行——这是GPU性能杀手之一。

避坑指南:我曾经在项目中写了一个if-else分支,结果warp里一半线程走if,一半走else。性能直接腰斩。后来我学乖了,尽量让同一个warp里的线程走同一个分支。

1.3 GPU vs CPU:谁该干什么?

我经常被问到:GPU能不能取代CPU?答案是不能。它们各有所长。

特性 CPU GPU
核心数 4-16个 数千个
单核性能 极强 较弱
适合任务 串行、逻辑复杂 并行、计算密集
内存延迟 低(缓存大) 高(显存远)
典型场景 操作系统、数据库 渲染、AI训练、科学计算

我个人习惯这样分配:CPU负责调度和逻辑控制,GPU负责计算。比如训练一个神经网络,CPU负责读取数据、做预处理、控制训练流程;GPU负责矩阵乘法、卷积这些计算密集型操作。

经验之谈:别把GPU当万能药。如果你的数据量很小(比如几百个点),或者计算逻辑分支特别多,GPU反而比CPU慢。因为启动GPU内核有开销,数据从CPU传到GPU也有开销。

1.4 GPU编程的生态系统

目前主流的GPU编程框架有三个:CUDA、OpenCL、ROCm。我主要用CUDA,但其他两个也值得了解。

CUDA(NVIDIA)

CUDA是NVIDIA的亲儿子。说实话,生态最好,文档最全,工具链最成熟。我刚开始学GPU编程时,就是跟着CUDA的官方教程走的。如果你用NVIDIA显卡,CUDA是首选。

// 一个简单的CUDA内核
__global__ void vecAdd(float *a, float *b, float *c, int n) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < n) {
        c[i] = a[i] + b[i];
    }
}

这段代码看着简单,但包含了GPU编程的核心概念:__global__表示这是GPU内核函数,blockIdxthreadIdx是线程索引,blockDim是线程块大小。

OpenCL(跨平台)

OpenCL是苹果搞的,后来交给Khronos组织维护。它的优点是跨平台——CPU、GPU、FPGA都能跑。但缺点也很明显:API太啰嗦,写起来像在写论文。我试过一次,配置上下文就要写几十行代码。

我的建议:如果你只做NVIDIA平台,用CUDA。如果你需要跨平台(比如AMD和NVIDIA都要支持),可以考虑OpenCL或SYCL。

ROCm(AMD)

ROCm是AMD的开源GPU计算平台。它试图兼容CUDA的编程模型,但说实话,生态还不够成熟。我有个朋友在AMD工作,他说ROCm在Linux上表现不错,但Windows支持还差点意思。

嗯,这里要提一句:HIP(Heterogeneous Interface for Portability)是ROCm的一部分,它可以把CUDA代码转成HIP代码,然后在AMD GPU上跑。如果你有CUDA代码想移植到AMD,可以试试这个。

1.5 本章知识体系

下面这张图总结了本章的核心内容:

GPU计算概述:知识体系 GPU计算概述 从CPU到GPU的演进 CPU:单核性能至上 GPU:并行计算为王 GPU架构特点:SIMT SM(流多处理器) Warp(32线程一组) GPU vs CPU适用场景 CPU:串行、逻辑复杂 GPU:并行、计算密集 GPU编程生态系统 CUDA(NVIDIA生态) OpenCL(跨平台) ROCm(AMD生态) 核心:理解并行思维,选择合适的工具

1.6 本章小结

这一章我们聊了GPU计算的来龙去脉。从CPU到GPU的演进,说白了就是人类对算力的贪婪永无止境。SIMT架构让GPU能以低成本实现大规模并行,但也要注意warp分支、内存访问这些坑。

我个人觉得,学GPU编程最重要的不是记住API,而是转变思维方式。从「我该怎么循环」变成「我该怎么并行」。这个转变需要时间,别急。

最后说一句:如果你刚开始学,建议先装好CUDA工具包,跑通一个向量加法。别一上来就搞复杂的。我当年就是太心急,结果debug到怀疑人生。


公众号:蓝海资料掘金营,微信deep3321