@@ -58,7 +58,7 @@ translation:
5858
5959## 概述
6060
61- 可以说, Python 是科学计算领域最流行的编程语言 。
61+ Python 是科学计算许多方面最流行的编程语言 。
6262
6363这得益于以下几点:
6464
@@ -101,35 +101,36 @@ mpl.rcParams['font.family'] = ['Source Han Serif SC'] # i18n
101101import random
102102```
103103
104-
105104## 主要科学库
106105
107106让我们简要回顾一下 Python 的科学库。
108107
109-
110108### 为什么需要它们?
111109
112- 我们使用科学库的一个原因是它们实现了我们想要使用的程序。
110+ 我们需要 Python 科学库有两个原因:
113111
114- * 数值积分、插值、线性代数、求根等。
112+ 1 . Python 体量小
113+ 2 . Python 速度慢
115114
116- 例如,使用现有的求根程序通常比从头编写一个新程序更好。
115+ ** Python 体量小 **
117116
118- (对于标准算法,如果社区能够统一使用一套由专家编写、并经用户调优以尽可能快速和健壮的共同实现,效率将达到最高!)
117+ 核心 Python 在设计上体量较小——这有助于优化、易用性和维护。
119118
120- 但这并不是我们使用 Python 科学库的唯一原因。
119+ 科学库提供了我们不想——也可能不应该——自己编写的程序:
121120
122- 另一个原因是纯 Python 速度不够快 。
121+ * 数值积分、插值、线性代数、求根等 。
123122
124- 因此,我们需要那些专门用于加速 Python 代码执行的库。
123+ ** Python 速度慢 **
125124
126- 它们通过两种策略来实现这一目标:
125+ 我们需要科学库的另一个原因是纯 Python 的速度相对较慢。
127126
128- 1 . 使用编译器将类 Python 语句转换为针对单一逻辑线程的快速机器码,以及
129- 2 . 在多个"工作单元"(例如 CPU、GPU 内部的各个线程)之间并行化任务。
127+ 科学库通过三种主要策略来加速执行:
130128
131- 我们将在本讲座及本系列剩余讲座中广泛讨论这些思想。
129+ 1 . 向量化:提供已编译的机器码以及使该代码可访问的接口
130+ 1 . JIT 编译:在运行时将类 Python 语句转换为快速机器码的编译器
131+ 2 . 并行化:将任务分配到多个线程 / CPU / GPU / TPU
132132
133+ 我们将在下文深入讨论这些思想。
133134
134135### Python 的科学生态系统
135136
@@ -151,8 +152,7 @@ import random
151152* Pandas 提供用于操作数据的类型和函数。
152153* Numba 提供一个即时编译器,与 NumPy 配合良好,有助于加速 Python 代码。
153154
154- 我们将在本系列讲座中广泛讨论所有这些库。
155-
155+ 我们将在本系列讲座中详细讨论所有这些库。
156156
157157## 纯 Python 速度慢
158158
@@ -162,7 +162,6 @@ import random
162162
163163对于这个主题,如果我们理解是什么导致了执行速度慢,将会很有帮助。
164164
165-
166165### 高级语言与低级语言
167166
168167像 Python 这样的高级语言是为人类优化的。
@@ -179,12 +178,10 @@ import random
179178
180179另一方面,Python 的标准实现(称为 CPython)无法与 C 或 Fortran 等编译语言的速度相媲美。
181180
182-
183181### 瓶颈在哪里?
184182
185183为什么会这样呢?
186184
187-
188185#### 动态类型
189186
190187``` {index} single: Dynamic Typing
@@ -215,14 +212,11 @@ a, b = ['foo'], ['bar']
215212a + b
216213```
217214
218- (我们说运算符 ` + ` 是* 重载的* ——它的动作取决于它所作用的对象的类型。)
219-
220215因此,在执行 ` a + b ` 时,Python 必须首先检查对象的类型,然后调用正确的操作。
221216
222- 这涉及到不可忽视的开销。
223-
224- 如果我们在一个紧密的循环中反复执行此表达式,这种不可忽视的开销就会变成巨大的开销。
217+ 这涉及到额外的开销。
225218
219+ 如果我们在一个紧密的循环中反复执行此表达式,这种开销就会变得很大。
226220
227221#### 静态类型
228222
@@ -257,7 +251,6 @@ int main(void) {
257251
258252无需类型检查,因此没有额外开销。
259253
260-
261254### 数据访问
262255
263256高级语言速度慢的另一个原因是数据访问。
@@ -266,22 +259,15 @@ int main(void) {
266259
267260#### 使用编译代码求和
268261
269- 在 C 或 Fortran 中,这些整数通常存储在数组中,数组是一种用于存储同类数据的简单数据结构。
270-
271- 这样的数组存储在单个连续的内存块中:
262+ 在 C 或 Fortran 中,整数数组存储在单个连续的内存块中:
272263
273- * 在现代计算机中,内存地址分配给每个字节(1字节 = 8位)。
274264* 例如,一个 64 位整数存储在 8 字节的内存中。
275265* $n$ 个这样的整数组成的数组占据 $8n$ 个* 连续* 的内存槽。
276266
277- 此外,编译器通过程序员的声明得知数据类型。
278-
279- * 在本例中为 64 位整数。
267+ 此外,数据类型在编译时是已知的。
280268
281269因此,每个连续的数据点都可以通过在内存空间中向前移动一个已知且固定的量来访问。
282270
283- * 在本例中为 8 字节。
284-
285271#### 在纯 Python 中求和
286272
287273Python 在一定程度上试图复制这些思想。
@@ -292,11 +278,7 @@ Python 在一定程度上试图复制这些思想。
292278
293279因此,访问数据值本身仍然存在开销。
294280
295- 这对速度是一个相当大的拖累。
296-
297- 事实上,内存流量通常是导致执行缓慢的主要因素。
298-
299-
281+ 这种开销是导致执行缓慢的主要因素。
300282
301283### 总结
302284
@@ -314,11 +296,6 @@ Python 在一定程度上试图复制这些思想。
314296
315297这个任务最好留给专门的编译器!
316298
317- 某些 Python 库在并行化科学代码方面具有出色的能力——我们将在后续内容中进一步讨论。
318-
319-
320-
321-
322299## 加速 Python
323300
324301在本节中,我们将介绍三种加速 Python 代码的相关技术。
@@ -327,8 +304,6 @@ Python 在一定程度上试图复制这些思想。
327304
328305稍后我们将研究具体的库以及它们如何实现这些思想。
329306
330-
331-
332307### {index}` 向量化 <single: Vectorization> `
333308
334309``` {index} single: Python; Vectorization
@@ -359,7 +334,7 @@ Python 在一定程度上试图复制这些思想。
359334``` {figure} /_static/lecture_specific/need_for_speed/matlab.png
360335```
361336
362-
337+ NumPy 使用类似的模型,灵感来自 MATLAB。
363338
364339### 向量化 vs 纯 Python 循环
365340
@@ -417,50 +392,39 @@ with qe.Timer():
417392
418393在本系列后续讲座中,我们将学习现代 Python 库如何利用即时编译器生成快速、高效、并行化的机器码。
419394
420-
421-
422-
423395## 并行化
424396
425397近年来,CPU 时钟速度(即单条逻辑链的运行速度)的增长已大幅放缓。
426398
427399芯片设计师和计算机程序员通过寻求一条不同的路径来应对这一放缓:并行化。
428400
429- 硬件制造商增加了每台机器中嵌入的核心数量(物理 CPU)。
430-
431- 对于程序员来说,挑战在于通过同时运行多个进程(即并行)来充分利用这些多个 CPU。
401+ 这涉及到:
432402
433- 这在科学编程中尤为重要,因为科学编程需要处理:
403+ 1 . 增加每台机器中嵌入的 CPU 数量
404+ 1 . 连接 GPU 和 TPU 等硬件加速器
434405
435- * 大量数据,以及
436- * CPU 密集型的模拟和其他计算。
406+ 对于程序员来说,挑战在于利用这些硬件并行运行多个进程。
437407
438408下面我们讨论科学计算中的并行化,重点关注:
439409
440- 1 . Python 中最佳的并行化工具 ,以及
410+ 1 . Python 中的并行化工具 ,以及
4414111 . 这些工具如何应用于定量经济学问题。
442412
443-
444413### CPU 上的并行化
445414
446415让我们回顾一下科学计算中常用的两种主要 CPU 并行化方式,并讨论它们的优缺点。
447416
448-
449417#### 多进程
450418
451- 多进程是指使用多个处理器并发执行多个进程。
452-
453- 在这个语境中,** 进程** 是一系列指令(即一个程序)。
419+ 多进程是指使用多个处理器并发执行多条逻辑线程。
454420
455- 多进程可以在一台拥有多个 CPU 的机器上进行,也可以在通过网络连接的多台机器上进行 。
421+ 多进程可以在一台拥有多个 CPU 的机器上进行,也可以在通过网络连接的机器集群上进行 。
456422
457- 在后一种情况下,这些机器的集合通常称为** 集群** 。
458-
459- 在多进程中,每个进程都有自己的内存空间,尽管物理内存芯片可能是共享的。
423+ 在多进程中,* 每个进程都有自己的内存空间* ,尽管物理内存芯片可能是共享的。
460424
461425#### 多线程
462426
463- 多线程与多进程类似,不同之处在于,在执行期间,所有线程共享同一内存空间 。
427+ 多线程与多进程类似,不同之处在于,在执行期间,所有线程 * 共享同一内存空间 * 。
464428
465429由于一些[ 遗留的设计特性] ( https://wiki.python.org/moin/GlobalInterpreterLock ) ,原生 Python 难以实现多线程。
466430
@@ -478,7 +442,6 @@ with qe.Timer():
478442
479443对于我们在这些讲座中所做的绝大多数工作,多线程就足够了。
480444
481-
482445### 硬件加速器
483446
484447虽然拥有多核的 CPU 已成为并行计算的标准,但随着专用硬件加速器的兴起,发生了更为深刻的变化。
@@ -504,7 +467,6 @@ TPU 是较新的发展,由 Google 专门为机器学习工作负载设计。
504467
505468与 GPU 一样,TPU 擅长并行执行大量矩阵运算。
506469
507-
508470#### 为何 TPU/GPU 至关重要
509471
510472使用硬件加速器带来的性能提升可能是惊人的。
@@ -515,7 +477,6 @@ TPU 是较新的发展,由 Google 专门为机器学习工作负载设计。
515477
516478这对科学计算尤为重要,因为许多算法天然地映射到 GPU 的并行架构上。
517479
518-
519480### 单 GPU 与 GPU 服务器
520481
521482访问 GPU 资源有两种常见方式:
@@ -530,7 +491,6 @@ TPU 是较新的发展,由 Google 专门为机器学习工作负载设计。
530491
531492现代 Python 库(如本系列讲座中广泛讨论的 JAX)可以以最少的代码改动自动检测并使用可用的 GPU。
532493
533-
534494#### 多 GPU 服务器
535495
536496对于规模更大的问题,包含多个 GPU(通常每台服务器 4-8 个 GPU)的服务器越来越普遍。
@@ -544,11 +504,10 @@ TPU 是较新的发展,由 Google 专门为机器学习工作负载设计。
544504
545505这使研究人员能够处理在单个 GPU 或 CPU 上不可行的问题。
546506
547-
548507### 总结
549508
550509GPU 计算正变得越来越容易获取,尤其是在 Python 中。
551510
552511一些 Python 科学库(如 JAX)现在支持 GPU 加速,对现有代码的改动极少。
553512
554- 我们将在后续讲座中更详细地探讨 GPU 计算,并将其应用于一系列经济学应用。
513+ 我们将在后续讲座中更详细地探讨 GPU 计算,并将其应用于一系列经济学应用。
0 commit comments