“既然 GPU 这么好,那为什么我们还要用 CPU?”

B站影视 2025-01-09 19:43 2

摘要:者按】在当今这个计算能力飞速发展的时代,GPU 的崛起无疑为诸多领域带来了革命性的变化。凭借其强大的并行处理能力,GPU 在深度学习、图像处理、科学计算等需要大量数值运算的场景中大放异彩,让许多之前难以想象的计算任务变得触手可及。然而,即便 GPU 有着诸多令

【CSDN 编

者按】在当今这个计算能力飞速发展的时代,GPU 的崛起无疑为诸多领域带来了革命性的变化。凭借其强大的并行处理能力,GPU 在深度学习、图像处理、科学计算等需要大量数值运算的场景中大放异彩,让许多之前难以想象的计算任务变得触手可及。然而,即便 GPU 有着诸多令人瞩目的优势,CPU 依然在我们的计算世界中扮演着不可或缺的角色。

tack.com/p/if-gpus-are-so-good-why-do-we-still

作者 | Teddy Wahle 翻译 | 郑丽媛

出品 | CSDN(ID:CSDNnews)

最近,一段 2009 年的老视频在 X 上走红,这段仅 90 秒的视频直观地展示了 CPU(中央处理器)与 GPU(图形处理器)之间的区别:

这个视频的主要内容是:CPU 和 GPU 进行了一场“绘画对决”。这两种处理器连接到一台可以发射彩弹的装置上。

其中,CPU 用了整整 30 秒才画出一个简单的笑脸:

而 GPU 则能瞬间画出《蒙娜丽莎》:

从这段视频中,我们可以得出的结论是:CPU 速度较慢,而 GPU 则快得多。不过此结论仅限于该视频,毕竟这个视频并未揭示关于 CPU 和 GPU 更深层次的细节。

每秒万亿次浮点运算(TFLOPS)

当我们说 GPU 比 CPU 性能更强时,通常会参考一个叫 TFLOPS 的测量指标,这个指标衡量的是处理器每秒可以执行多少万亿次数学运算。例如,Nvidia 的 A100 GPU 可以达到 9.7 TFLOPS(每秒 9.7 万亿次运算),而最新的 Intel 24 核处理器只能达到 0.33 TFLOPS。这意味着,即便是中等配置的 GPU,其速度也至少是顶级 CPU 的 30 倍以上。

然而,我的 MacBook(搭载 Apple M3 芯片)中既有 CPU 也有 GPU——为什么呢?我们就不能完全抛弃这些“极其缓慢”的 CPU 吗?

不同类型的程序

为了更好地理解为什么我们需要 CPU 与 GPU 两种处理器,让我们先定义两类程序:顺序程序和并行程序。

(1)顺序程序

顺序程序是指所有指令必须一个接一个、按部就班地依次执行。比如下面这段代码:

在这个例子中,n 需要连续乘以 100 个随机数,且每个步骤都依赖于前一步的结果。如果你要手动进行这些计算,就不能将任务分给朋友说:“你算前 50 步,我算后 50 步。”因为你们都需要按照顺序执行所有步骤,才能得到准确的结果。

(2)并行程序

并行程序则是指多个指令可以同时执行,因为它们之间不存在依赖关系。例如:

def parallel_multiply: numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] results = for n in numbers: results.append(n * 2) return results

在这个例子中,十个乘法操作完全独立,彼此间没有依赖性。关键在于,这些步骤的顺序并不重要。因此,如果你想要分工合作,就可以说:“你负责计算奇数,我负责计算偶数。”这样,两人可以分别且同步工作,最终得到正确答案。

错误的二分法

实际上,这种区分是一种错误的二分法。事实上,大多数实际应用都是由顺序和并行代码混合组成的,每个程序中都会有一部分代码可以并行化。

举个例子,假设有一个程序需要运行 20 次计算,其中前 10 次互相依赖,但后 10 个计算可以并行执行。我们就会说这个程序是“50% 可并行化”,即一半的指令可以独立执行,也就是说它们可以同时进行。结合之前的两个示例,我们可以将其构造成一段 50% 可并行化的代码:

sequential_list = [1] for _ in range(9): next_value = sequential_list[-1] * random.randint(1, 10) sequential_list.append(next_value) # Part 2: Each step is independent of each other parallel_results = for n in sequential_list: parallel_results.append(n * 2) return sequential_list, parallel_results

在这个例子中,第一部分确实必须顺序执行,因为 sequential_list 中的每个数值都依赖于前一个值。但第二部分则可以对已完成列表中的每个值执行独立的操作。

对于第一部分的计算,你需要等到前一个数值计算完毕才能继续;但在有了完整列表之后,你就可以将乘法操作分配给所有可用的工作单元,从而实现并行处理。

不同的处理器适用于不同类型的程序

总体来说,CPU 适合运行顺序程序,而 GPU 更擅长执行并行程序。这主要是因为 CPU 和 GPU 在设计上有根本性的差异。

CPU 拥有少量的大核心(如 Apple M3 有 8 个核心),而 GPU 则包含大量的小核心(例如 NVIDIA H100 GPU 有数千个核心)。这就是为什么 GPU 非常适合运行高度并行的程序——它拥有数千个简单的核心,可以同时对不同的数据执行相同的操作。

渲染视频游戏图形就是一个需要大量简单重复计算的应用场景。想象一下,游戏画面就是一个巨大的像素矩阵。当你突然将角色向右转时,屏幕上所有的像素都需要重新计算新的颜色值。好在,屏幕顶部像素的计算与屏幕底部像素的计算是相互独立的,因此,这些计算可以被分配到 GPU 的数千个核心上并行执行。这就是为什么 GPU 在游戏中至关重要的原因。

CPU 擅长处理随机事件

在处理高度并行的任务时,例如乘对一个包含 10,000 个独立数字的矩阵进行乘法运算,CPU 的速度远远不如 GPU。然而,CPU 在执行复杂的顺序处理和决策制定时,却能展现出卓越的性能。

你可以把 CPU 核心比作繁忙餐厅厨房中的主厨。这个主厨能够:

● 在 VIP 客人到来并提出特别饮食要求时,立即调整自己的烹饪计划;

● 在准备精致酱汁和检查烤蔬菜之间无缝切换;

● 遇到突发状况(比如停电)时,能重新组织整个厨房的工作流程来应对意外;

● 协调多道菜肴,确保它们在恰到好处的时刻热腾腾地送到桌上;

● 在处理不同状态的几十个订单时,依然保持食品质量。

相比之下,GPU 核心就像一百名擅长重复任务的厨师——他们能在 2 秒钟内切好一个洋葱,但无法有效管理整个厨房。如果你要求 GPU 处理餐厅服务中不断变化的需求,它可能会力不从心。

这就是为什么 CPU 对于运行计算机的操作系统至关重要。现代计算机面临着大量不可预测的事件:应用程序的启动与停止、网络连接的中断、文件的访问以及用户在屏幕上的随机点击等。CPU 非常擅长处理这些任务,同时保持系统的响应速度。它可以立即从帮助 Chrome 渲染网页切换到处理 Zoom 视频通话,再到处理新的 USB 设备连接——同时还在跟踪系统资源,确保每个应用程序都能公平地获得资源

因此,尽管 GPU 在并行处理上表现出色,但 CPU 因其独特的处理复杂逻辑和适应变化条件的能力,仍然是必不可少的。像 Apple M3 这样的现代芯片将二者结合,既具备了 CPU 的灵活性,又能提供 GPU 的强大计算能力。

事实上,如果要重新制作那个绘画视频,还有一个更准确的版本:让 CPU 负责管理图像下载和内存分配,然后将工作交给 GPU 来迅速渲染像素。

“侯捷老师的课程让我彻底理解了STL的底层原理!”

C++权威大师侯捷亲授,四门精品课程全方位覆盖C++核心知识:

《STL标准库与泛型编程》:深度解构STL设计精髓,掌握泛型编程的强大力量

《C++新标准11/14》:精准解析新标准,轻松升级现代C++技能

《C++面向对象开发》:系统学习面向对象思想,构建灵活高效的程序架构

《C++内存管理机制》:破解内存管理难题,让资源使用更加安全高效

现在报名,还可尊享专属纸质版讲义,学以致用,事半功倍!

来源:CSDN

相关推荐