@@ -58,7 +58,7 @@ translation:
5858
5959## 概述
6060
61- 可以说, Python 是科学计算领域最流行的编程语言 。
61+ Python 是科学计算许多方面最流行的编程语言 。
6262
6363这得益于以下几点:
6464
@@ -102,35 +102,36 @@ mpl.rcParams['font.family'] = ['Source Han Serif SC'] # i18n
102102import random
103103```
104104
105-
106105## 主要科学库
107106
108107让我们简要回顾一下 Python 的科学库。
109108
110-
111109### 为什么需要它们?
112110
113- 我们使用科学库的一个原因是它们实现了我们想要使用的程序。
111+ 我们需要 Python 科学库有两个原因:
114112
115- * 数值积分、插值、线性代数、求根等。
113+ 1 . Python 体量小
114+ 2 . Python 速度慢
116115
117- 例如,使用现有的求根程序通常比从头编写一个新程序更好。
116+ ** Python 体量小 **
118117
119- (对于标准算法,如果社区能够统一使用一套由专家编写、并经用户调优以尽可能快速和健壮的共同实现,效率将达到最高!)
118+ 核心 Python 在设计上体量较小——这有助于优化、易用性和维护。
120119
121- 但这并不是我们使用 Python 科学库的唯一原因。
120+ 科学库提供了我们不想——也可能不应该——自己编写的程序:
122121
123- 另一个原因是纯 Python 速度不够快 。
122+ * 数值积分、插值、线性代数、求根等 。
124123
125- 因此,我们需要那些专门用于加速 Python 代码执行的库。
124+ ** Python 速度慢 **
126125
127- 它们通过两种策略来实现这一目标:
126+ 我们需要科学库的另一个原因是纯 Python 的速度相对较慢。
128127
129- 1 . 使用编译器将类 Python 语句转换为针对单一逻辑线程的快速机器码,以及
130- 2 . 在多个"工作单元"(例如 CPU、GPU 内部的各个线程)之间并行化任务。
128+ 科学库通过三种主要策略来加速执行:
131129
132- 我们将在本讲座及本系列剩余讲座中广泛讨论这些思想。
130+ 1 . 向量化:提供已编译的机器码以及使该代码可访问的接口
131+ 1 . JIT 编译:在运行时将类 Python 语句转换为快速机器码的编译器
132+ 2 . 并行化:将任务分配到多个线程 / CPU / GPU / TPU
133133
134+ 我们将在下文深入讨论这些思想。
134135
135136### Python 的科学生态系统
136137
@@ -152,8 +153,7 @@ import random
152153* Pandas 提供用于操作数据的类型和函数。
153154* Numba 提供一个即时编译器,与 NumPy 配合良好,有助于加速 Python 代码。
154155
155- 我们将在本系列讲座中广泛讨论所有这些库。
156-
156+ 我们将在本系列讲座中详细讨论所有这些库。
157157
158158## 纯 Python 速度慢
159159
@@ -163,7 +163,6 @@ import random
163163
164164对于这个主题,如果我们理解是什么导致了执行速度慢,将会很有帮助。
165165
166-
167166### 高级语言与低级语言
168167
169168像 Python 这样的高级语言是为人类优化的。
@@ -180,12 +179,10 @@ import random
180179
181180另一方面,Python 的标准实现(称为 CPython)无法与 C 或 Fortran 等编译语言的速度相媲美。
182181
183-
184182### 瓶颈在哪里?
185183
186184为什么会这样呢?
187185
188-
189186#### 动态类型
190187
191188``` {index} single: Dynamic Typing
@@ -216,14 +213,11 @@ a, b = ['foo'], ['bar']
216213a + b
217214```
218215
219- (我们说运算符 ` + ` 是* 重载的* ——它的动作取决于它所作用的对象的类型。)
220-
221216因此,在执行 ` a + b ` 时,Python 必须首先检查对象的类型,然后调用正确的操作。
222217
223- 这涉及到不可忽视的开销。
224-
225- 如果我们在一个紧密的循环中反复执行此表达式,这种不可忽视的开销就会变成巨大的开销。
218+ 这涉及到额外的开销。
226219
220+ 如果我们在一个紧密的循环中反复执行此表达式,这种开销就会变得很大。
227221
228222#### 静态类型
229223
@@ -258,7 +252,6 @@ int main(void) {
258252
259253无需类型检查,因此没有额外开销。
260254
261-
262255### 数据访问
263256
264257高级语言速度慢的另一个原因是数据访问。
@@ -267,22 +260,15 @@ int main(void) {
267260
268261#### 使用编译代码求和
269262
270- 在 C 或 Fortran 中,这些整数通常存储在数组中,数组是一种用于存储同类数据的简单数据结构。
271-
272- 这样的数组存储在单个连续的内存块中:
263+ 在 C 或 Fortran 中,整数数组存储在单个连续的内存块中:
273264
274- * 在现代计算机中,内存地址分配给每个字节(1字节 = 8位)。
275265* 例如,一个 64 位整数存储在 8 字节的内存中。
276266* $n$ 个这样的整数组成的数组占据 $8n$ 个* 连续* 的内存槽。
277267
278- 此外,编译器通过程序员的声明得知数据类型。
279-
280- * 在本例中为 64 位整数。
268+ 此外,数据类型在编译时是已知的。
281269
282270因此,每个连续的数据点都可以通过在内存空间中向前移动一个已知且固定的量来访问。
283271
284- * 在本例中为 8 字节。
285-
286272#### 在纯 Python 中求和
287273
288274Python 在一定程度上试图复制这些思想。
@@ -293,11 +279,7 @@ Python 在一定程度上试图复制这些思想。
293279
294280因此,访问数据值本身仍然存在开销。
295281
296- 这对速度是一个相当大的拖累。
297-
298- 事实上,内存流量通常是导致执行缓慢的主要因素。
299-
300-
282+ 这种开销是导致执行缓慢的主要因素。
301283
302284### 总结
303285
@@ -315,11 +297,6 @@ Python 在一定程度上试图复制这些思想。
315297
316298这个任务最好留给专门的编译器!
317299
318- 某些 Python 库在并行化科学代码方面具有出色的能力——我们将在后续内容中进一步讨论。
319-
320-
321-
322-
323300## 加速 Python
324301
325302在本节中,我们将介绍三种加速 Python 代码的相关技术。
@@ -328,8 +305,6 @@ Python 在一定程度上试图复制这些思想。
328305
329306稍后我们将研究具体的库以及它们如何实现这些思想。
330307
331-
332-
333308### {index}` 向量化 <single: Vectorization> `
334309
335310``` {index} single: Python; Vectorization
@@ -360,7 +335,7 @@ Python 在一定程度上试图复制这些思想。
360335``` {figure} /_static/lecture_specific/need_for_speed/matlab.png
361336```
362337
363-
338+ NumPy 使用类似的模型,灵感来自 MATLAB。
364339
365340### 向量化 vs 纯 Python 循环
366341
@@ -418,50 +393,39 @@ with qe.Timer():
418393
419394在本系列后续讲座中,我们将学习现代 Python 库如何利用即时编译器生成快速、高效、并行化的机器码。
420395
421-
422-
423-
424396## 并行化
425397
426398近年来,CPU 时钟速度(即单条逻辑链的运行速度)的增长已大幅放缓。
427399
428400芯片设计师和计算机程序员通过寻求一条不同的路径来应对这一放缓:并行化。
429401
430- 硬件制造商增加了每台机器中嵌入的核心数量(物理 CPU)。
431-
432- 对于程序员来说,挑战在于通过同时运行多个进程(即并行)来充分利用这些多个 CPU。
402+ 这涉及到:
433403
434- 这在科学编程中尤为重要,因为科学编程需要处理:
404+ 1 . 增加每台机器中嵌入的 CPU 数量
405+ 1 . 连接 GPU 和 TPU 等硬件加速器
435406
436- * 大量数据,以及
437- * CPU 密集型的模拟和其他计算。
407+ 对于程序员来说,挑战在于利用这些硬件并行运行多个进程。
438408
439409下面我们讨论科学计算中的并行化,重点关注:
440410
441- 1 . Python 中最佳的并行化工具 ,以及
411+ 1 . Python 中的并行化工具 ,以及
4424121 . 这些工具如何应用于定量经济学问题。
443413
444-
445414### CPU 上的并行化
446415
447416让我们回顾一下科学计算中常用的两种主要 CPU 并行化方式,并讨论它们的优缺点。
448417
449-
450418#### 多进程
451419
452- 多进程是指使用多个处理器并发执行多个进程。
453-
454- 在这个语境中,** 进程** 是一系列指令(即一个程序)。
420+ 多进程是指使用多个处理器并发执行多条逻辑线程。
455421
456- 多进程可以在一台拥有多个 CPU 的机器上进行,也可以在通过网络连接的多台机器上进行 。
422+ 多进程可以在一台拥有多个 CPU 的机器上进行,也可以在通过网络连接的机器集群上进行 。
457423
458- 在后一种情况下,这些机器的集合通常称为** 集群** 。
459-
460- 在多进程中,每个进程都有自己的内存空间,尽管物理内存芯片可能是共享的。
424+ 在多进程中,* 每个进程都有自己的内存空间* ,尽管物理内存芯片可能是共享的。
461425
462426#### 多线程
463427
464- 多线程与多进程类似,不同之处在于,在执行期间,所有线程共享同一内存空间 。
428+ 多线程与多进程类似,不同之处在于,在执行期间,所有线程 * 共享同一内存空间 * 。
465429
466430由于一些[ 遗留的设计特性] ( https://wiki.python.org/moin/GlobalInterpreterLock ) ,原生 Python 难以实现多线程。
467431
@@ -479,7 +443,6 @@ with qe.Timer():
479443
480444对于我们在这些讲座中所做的绝大多数工作,多线程就足够了。
481445
482-
483446### 硬件加速器
484447
485448虽然拥有多核的 CPU 已成为并行计算的标准,但随着专用硬件加速器的兴起,发生了更为深刻的变化。
@@ -505,7 +468,6 @@ TPU 是较新的发展,由 Google 专门为机器学习工作负载设计。
505468
506469与 GPU 一样,TPU 擅长并行执行大量矩阵运算。
507470
508-
509471#### 为何 TPU/GPU 至关重要
510472
511473使用硬件加速器带来的性能提升可能是惊人的。
@@ -516,7 +478,6 @@ TPU 是较新的发展,由 Google 专门为机器学习工作负载设计。
516478
517479这对科学计算尤为重要,因为许多算法天然地映射到 GPU 的并行架构上。
518480
519-
520481### 单 GPU 与 GPU 服务器
521482
522483访问 GPU 资源有两种常见方式:
@@ -531,7 +492,6 @@ TPU 是较新的发展,由 Google 专门为机器学习工作负载设计。
531492
532493现代 Python 库(如本系列讲座中广泛讨论的 JAX)可以以最少的代码改动自动检测并使用可用的 GPU。
533494
534-
535495#### 多 GPU 服务器
536496
537497对于规模更大的问题,包含多个 GPU(通常每台服务器 4-8 个 GPU)的服务器越来越普遍。
@@ -545,11 +505,10 @@ TPU 是较新的发展,由 Google 专门为机器学习工作负载设计。
545505
546506这使研究人员能够处理在单个 GPU 或 CPU 上不可行的问题。
547507
548-
549508### 总结
550509
551510GPU 计算正变得越来越容易获取,尤其是在 Python 中。
552511
553512一些 Python 科学库(如 JAX)现在支持 GPU 加速,对现有代码的改动极少。
554513
555- 我们将在后续讲座中更详细地探讨 GPU 计算,并将其应用于一系列经济学应用。
514+ 我们将在后续讲座中更详细地探讨 GPU 计算,并将其应用于一系列经济学应用。
0 commit comments