@@ -14,31 +14,25 @@ translation:
1414 Major Scientific Libraries : 主要科学库
1515 Major Scientific Libraries::Why do we need them? : 为什么需要它们?
1616 Major Scientific Libraries::Python's Scientific Ecosystem : Python 的科学生态系统
17- Pure Python is slow : 纯 Python 速度慢
18- Pure Python is slow::High vs low level code : 高级语言与低级语言
19- Pure Python is slow::Where are the bottlenecks? : 瓶颈在哪里?
20- Pure Python is slow::Where are the bottlenecks?::Dynamic typing : 动态类型
21- Pure Python is slow::Where are the bottlenecks?::Static types : 静态类型
22- Pure Python is slow::Data Access : 数据访问
23- Pure Python is slow::Data Access::Summing with Compiled Code : 使用编译代码求和
24- Pure Python is slow::Data Access::Summing in Pure Python : 在纯 Python 中求和
25- Pure Python is slow::Summary : 总结
17+ Why is Pure Python Slow? : 为什么纯 Python 速度较慢?
18+ Why is Pure Python Slow?::Type Checking : 类型检查
19+ Why is Pure Python Slow?::Type Checking::Dynamic typing : 动态类型
20+ Why is Pure Python Slow?::Type Checking::Static types : 静态类型
21+ Why is Pure Python Slow?::Data Access : 数据访问
22+ Why is Pure Python Slow?::Data Access::Summing with Compiled Code : 使用编译代码求和
23+ Why is Pure Python Slow?::Data Access::Summing in Pure Python : 用纯 Python 求和
24+ Why is Pure Python Slow?::Summary : 总结
2625 Accelerating Python : 加速 Python
2726 Accelerating Python::Vectorization : 向量化
28- Accelerating Python::Vectorization vs for pure Python loops : 向量化 vs 纯 Python 循环
27+ Accelerating Python::Vectorization vs pure Python loops : 向量化 vs 纯 Python 循环
2928 Accelerating Python::JIT compilers : JIT 编译器
3029 Parallelization : 并行化
3130 Parallelization::Parallelization on CPUs : CPU 上的并行化
32- Parallelization::Parallelization on CPUs::Multiprocessing : 多进程
3331 Parallelization::Parallelization on CPUs::Multithreading : 多线程
34- Parallelization::Parallelization on CPUs::Advantages and Disadvantages : 优缺点
32+ Parallelization::Parallelization on CPUs::Multiprocessing : 多进程
33+ Parallelization::Parallelization on CPUs::Which Should We Use? : 应该选择哪种方式?
3534 Parallelization::Hardware Accelerators : 硬件加速器
36- Parallelization::Hardware Accelerators::GPUs and TPUs : GPU 和 TPU
37- Parallelization::Hardware Accelerators::Why TPUs/GPUs Matter : 为何 TPU/GPU 至关重要
38- Parallelization::Single GPUs vs GPU Servers : 单 GPU 与 GPU 服务器
39- Parallelization::Single GPUs vs GPU Servers::Single GPU Systems : 单 GPU 系统
40- Parallelization::Single GPUs vs GPU Servers::Multi-GPU Servers : 多 GPU 服务器
41- Parallelization::Summary : 总结
35+ Parallelization::Accessing GPU Resources : 访问 GPU 资源
4236---
4337
4438(speed)=
@@ -153,60 +147,44 @@ import random
153147* Pandas 提供用于操作数据的类型和函数。
154148* Numba 提供一个即时编译器,与 NumPy 配合良好,有助于加速 Python 代码。
155149
156- 我们将在本系列讲座中详细讨论所有这些库。
157-
158- ## 纯 Python 速度慢
159-
160- 如上所述,科学库的一大吸引力在于更快的执行速度。
161-
162- 我们将讨论科学库如何帮助我们加速代码。
163-
164- 对于这个主题,如果我们理解是什么导致了执行速度慢,将会很有帮助。
165-
166- ### 高级语言与低级语言
167-
168- 像 Python 这样的高级语言是为人类优化的。
169-
170- 这意味着程序员可以将许多细节留给运行时环境处理,例如:
150+ 我们将在本系列讲座中广泛讨论所有这些库。
171151
172- * 指定变量类型
173- * 内存分配与释放
174- * 等等。
152+ ## 为什么纯 Python 速度较慢?
175153
176- 此外,纯 Python 由一个 [ 解释器 ] ( https://en.wikipedia.org/wiki/Interpreter_(computing) ) 运行,该解释器逐条语句地执行代码 。
154+ 如上所述,用纯 Python 编写的数值计算代码相对较慢 。
177155
178- 这使得 Python 灵活、交互性强、易于编写、易于阅读,并且相对容易调试 。
156+ 让我们尝试理解是什么导致了执行速度缓慢 。
179157
180- 另一方面,Python 的标准实现(称为 CPython)无法与 C 或 Fortran 等编译语言的速度相媲美。
158+ ### 类型检查
181159
182- ### 瓶颈在哪里?
160+ 纯 Python 操作中的一个开销来源是类型检查。
183161
184- 为什么会这样呢?
162+ 让我们尝试理解其中的问题。
185163
186164#### 动态类型
187165
188166``` {index} single: Dynamic Typing
189167```
190168
191- 考虑这个 Python 操作:
169+ 考虑以下 Python 操作
192170
193171``` {code-cell} python3
194172a, b = 10, 10
195173a + b
196174```
197175
198- 即使对于这个简单的操作,Python 解释器也有相当多的工作要做 。
176+ 即使对于这个简单的操作,Python 解释器也需要做相当多的工作 。
199177
200- 例如,在语句 ` a + b ` 中,解释器必须知道调用哪个操作 。
178+ 例如,在语句 ` a + b ` 中,解释器必须知道应该调用哪种操作 。
201179
202- 如果 ` a ` 和 ` b ` 是字符串,那么 ` a + b ` 需要字符串连接:
180+ 如果 ` a ` 和 ` b ` 是字符串,那么 ` a + b ` 需要执行字符串拼接
203181
204182``` {code-cell} python3
205183a, b = 'foo', 'bar'
206184a + b
207185```
208186
209- 如果 ` a ` 和 ` b ` 是列表,那么 ` a + b ` 需要列表连接:
187+ 如果 ` a ` 和 ` b ` 是列表,那么 ` a + b ` 需要执行列表拼接
210188
211189``` {code-cell} python3
212190a, b = ['foo'], ['bar']
@@ -224,9 +202,9 @@ a + b
224202``` {index} single: Static Types
225203```
226204
227- 编译语言通过显式的静态类型来避免这些开销 。
205+ 编译型语言通过显式的静态类型来避免这些开销 。
228206
229- 例如,考虑以下 C 代码,它对从 1 到 10 的整数求和:
207+ 例如,考虑以下 C 代码,它计算从 1 到 10 的整数之和
230208
231209``` {code-block} c
232210:class: no-execute
@@ -244,58 +222,58 @@ int main(void) {
244222}
245223```
246224
247- 变量 ` i ` 和 ` sum ` 被明确声明为整数 。
225+ 变量 ` i ` 和 ` sum ` 被显式声明为整数类型 。
248226
249- 此外,当我们写出 ` int i ` 这样的语句时,我们是在向编译器承诺,在程序执行的整个过程中 ,` i ` 将* 始终* 是一个整数。
227+ 此外,当我们写下 ` int i ` 这样的语句时,我们是在向编译器承诺:在整个程序执行过程中 ,` i ` 将* 始终* 是一个整数。
250228
251229因此,表达式 ` sum + i ` 中加法的含义是完全明确的。
252230
253- 无需类型检查,因此没有额外开销 。
231+ 无需进行类型检查,也就不存在额外开销 。
254232
255233### 数据访问
256234
257- 高级语言速度慢的另一个原因是数据访问 。
235+ 高级语言速度较慢的另一个原因是数据访问方式 。
258236
259- 为了说明这一点,让我们考虑对一些数据求和的问题 ——比如,一组整数 。
237+ 为了说明这一点,让我们考虑对某些数据求和的问题 ——比如,一组整数的集合 。
260238
261239#### 使用编译代码求和
262240
263- 在 C 或 Fortran 中,整数数组存储在单个连续的内存块中:
241+ 在 C 或 Fortran 中,整数数组存储在一块连续的内存空间中
264242
265- * 例如,一个 64 位整数存储在 8 字节的内存中 。
266- * $n$ 个这样的整数组成的数组占据 $8n$ 个 * 连续 * 的内存槽 。
243+ * 例如,一个 64 位整数占用 8 个字节的内存 。
244+ * 由 $n$ 个这样的整数组成的数组占用 $8n$ 个连续字节 。
267245
268246此外,数据类型在编译时是已知的。
269247
270248因此,每个连续的数据点都可以通过在内存空间中向前移动一个已知且固定的量来访问。
271249
272- #### 在纯 Python 中求和
250+ #### 用纯 Python 求和
273251
274- Python 在一定程度上试图复制这些思想 。
252+ Python 在一定程度上尝试复现这些思路 。
275253
276254例如,在标准 Python 实现(CPython)中,列表元素被放置在某种意义上连续的内存位置。
277255
278- 然而,这些列表元素更像是指向数据的指针,而非实际数据 。
256+ 然而,这些列表元素更像是指向数据的指针,而不是实际的数据本身 。
279257
280- 因此,访问数据值本身仍然存在开销 。
258+ 因此,访问数据值本身仍然存在额外开销 。
281259
282- 这种开销是导致执行缓慢的主要因素 。
260+ 这种开销是导致执行速度缓慢的主要原因之一 。
283261
284262### 总结
285263
286- 上面的讨论是否意味着我们应该对所有事情都切换到 C 或 Fortran?
264+ 上述讨论是否意味着我们应该将所有工作都切换到 C 或 Fortran?
287265
288266答案是:绝对不是!
289267
290- 对于任何给定的程序,相对而言只有少数几行代码对时间要求严苛 。
268+ 对于任何给定的程序,真正对时间敏感的代码行数相对较少 。
291269
292- 因此,用 Python 这样的高生产力语言编写大部分代码要高效得多 。
270+ 因此,用 Python 这样的高生产力语言编写大部分代码效率要高得多 。
293271
294- 此外,即使对于那些* 确实* 对时间要求严苛的代码行 ,我们现在也可以通过使用 Python 的科学库,达到甚至超过从 C 或 Fortran 编译的二进制文件的速度 。
272+ 此外,即使对于那些* 确实* 对时间敏感的代码行 ,我们现在也可以通过使用 Python 的科学计算库来达到甚至超越由 C 或 Fortran 编译的二进制文件的性能 。
295273
296- 在这一点上,我们强调,在过去几年中,加速代码基本上已经与并行化同义 。
274+ 在这一点上,我们强调,在过去几年中,代码加速在本质上已经与并行化画上了等号 。
297275
298- 这个任务最好留给专门的编译器 !
276+ 这项任务最好留给专门的编译器来完成 !
299277
300278## 加速 Python
301279
@@ -335,7 +313,7 @@ Python 在一定程度上试图复制这些思想。
335313``` {figure} /_static/lecture_specific/need_for_speed/matlab.png
336314```
337315
338- NumPy 使用类似的模型,灵感来自 MATLAB。
316+ NumPy 使用类似的模型,灵感来源于 MATLAB
339317
340318### 向量化 vs 纯 Python 循环
341319
@@ -404,7 +382,7 @@ with qe.Timer():
4043821 . 增加每台机器中嵌入的 CPU 数量
4053831 . 连接 GPU 和 TPU 等硬件加速器
406384
407- 对于程序员来说,挑战在于利用这些硬件并行运行多个进程 。
385+ 对于程序员来说,挑战在于充分利用这些硬件,同时运行多个进程(即并行) 。
408386
409387下面我们讨论科学计算中的并行化,重点关注:
410388
@@ -423,92 +401,64 @@ with qe.Timer():
423401
424402在多进程中,* 每个进程都有自己的内存空间* ,尽管物理内存芯片可能是共享的。
425403
426- #### 多线程
404+ 所有线程共享同一内存空间,因此它们可以在不复制数据的情况下对同一数组进行读写。
427405
428- 多线程与多进程类似,不同之处在于,在执行期间,所有线程 * 共享同一内存空间 * 。
406+ 例如,当对大型数组的数值操作在现代笔记本电脑上运行时,工作负载可以分配到机器的多个 CPU 核心上,每个核心处理数组的一部分 。
429407
408+ ``` {note}
430409由于一些[遗留的设计特性](https://wiki.python.org/moin/GlobalInterpreterLock),原生 Python 难以实现多线程。
431-
432410但这对于 NumPy 和 Numba 等科学库来说并不是限制。
433-
434411从这些库导入的函数和经过 JIT 编译的代码在低级执行环境中运行,Python 的遗留限制在那里并不适用。
412+ ```
435413
436- #### 优缺点
437-
438- 多线程更加轻量,因为大多数系统资源和内存资源由线程共享。
414+ #### 多进程
439415
440- 此外,多个线程访问共享内存池这一事实对于数值编程来说极为方便 。
416+ 多进程是指运行多个独立进程,每个进程都有自己独立的内存空间 。
441417
442- 另一方面,多进程更灵活,可以分布在集群中 。
418+ 由于内存不共享,进程之间通过相互传递数据进行通信 。
443419
444- 对于我们在这些讲座中所做的绝大多数工作,多线程就足够了 。
420+ 多进程可以在单台机器上运行,也可以分布在通过网络连接的多台机器(集群)上 。
445421
446- ### 硬件加速器
422+ #### 应该选择哪种方式?
447423
448- 虽然拥有多核的 CPU 已成为并行计算的标准,但随着专用硬件加速器的兴起,发生了更为深刻的变化 。
424+ 对于单台机器上的数值工作,通常首选多线程——它更加轻量,且共享内存模型非常便利 。
449425
450- 这些加速器专门为科学计算、机器学习和数据科学中出现的高度并行计算而设计 。
426+ 当需要扩展到单台机器之外时,多进程就变得重要了 。
451427
452- #### GPU 和 TPU
428+ 对于我们在这些讲座中所做的绝大多数工作,多线程就足够了。
453429
454- 两种最重要的硬件加速器类型是:
430+ ### 硬件加速器
455431
456- * ** GPU** (图形处理单元)和
457- * ** TPU** (张量处理单元)。
432+ 并行化的一个更为重要的来源来自专用硬件加速器,尤其是 ** GPU** (图形处理单元)。
458433
459434GPU 最初是为渲染图形而设计的,这需要同时对许多像素执行相同的操作。
460435
461436``` {figure} /_static/lecture_specific/need_for_speed/geforce.png
462437:scale: 40
463438```
464439
465- 科学家和工程师意识到,这种架构——许多简单的处理器并行工作——非常适合科学计算任务。
466-
467- TPU 是较新的发展,由 Google 专门为机器学习工作负载设计。
468-
469- 与 GPU 一样,TPU 擅长并行执行大量矩阵运算。
470-
471- #### 为何 TPU/GPU 至关重要
472-
473- 使用硬件加速器带来的性能提升可能是惊人的。
474-
475- 例如,一块现代 GPU 可以包含数千个小型处理核心,而 CPU 中通常只有 8 到 64 个核心。
476-
477- 当一个问题可以表示为对数据数组进行许多独立操作时,GPU 的速度可以比 CPU 快几个数量级。
478-
479- 这对科学计算尤为重要,因为许多算法天然地映射到 GPU 的并行架构上。
480-
481- ### 单 GPU 与 GPU 服务器
440+ 这种架构——数千个简单核心对不同数据点执行相同指令——恰好非常适合科学计算。
482441
483- 访问 GPU 资源有两种常见方式:
442+ ``` {note}
443+ **核心**是芯片中的一个独立处理单元——一种可以自主执行指令的电路。CPU 通常拥有少量强大的核心,每个核心都能处理复杂的操作序列。而 GPU 则集成了数千个更小、更简单的核心,每个核心专门执行基本的算术运算。GPU 的强大之处在于让所有这些核心同时处理同一问题的不同部分。
444+ ```
484445
485- #### 单 GPU 系统
446+ 当一个计算可以表示为对大型数据数组进行独立操作时,GPU 的速度可以比 CPU 快几个数量级。
486447
487- 许多工作站和笔记本电脑现在配备了性能强劲的 GPU,或者可以安装 GPU 。
448+ 由 Google 为机器学习设计的 ** TPU ** (张量处理单元)遵循类似的理念,专门针对大规模并行矩阵运算进行优化 。
488449
489- 单块现代 GPU 可以显著加速许多科学计算任务。
450+ ### 访问 GPU 资源
490451
491- 对于个人研究人员和小型项目,单块 GPU 通常就足够了。
452+ 许多工作站和笔记本电脑现在都配备了性能强劲的 GPU,对于个人研究项目来说,单块现代 GPU 通常就足够了。
492453
493454现代 Python 库(如本系列讲座中广泛讨论的 JAX)可以以最少的代码改动自动检测并使用可用的 GPU。
494455
495- #### 多 GPU 服务器
496-
497- 对于规模更大的问题,包含多个 GPU(通常每台服务器 4-8 个 GPU)的服务器越来越普遍。
456+ 对于规模更大的问题,包含多个 GPU(通常每台机器 4--8 个 GPU)的服务器越来越普遍。
498457
499458``` {figure} /_static/lecture_specific/need_for_speed/dgx.png
500459:scale: 40
501460```
502461
503-
504- 借助适当的软件,计算可以分布在多个 GPU 上,无论是在单台服务器内还是跨多台服务器。
505-
506- 这使研究人员能够处理在单个 GPU 或 CPU 上不可行的问题。
507-
508- ### 总结
509-
510- GPU 计算正变得越来越容易获取,尤其是在 Python 中。
511-
512- 一些 Python 科学库(如 JAX)现在支持 GPU 加速,对现有代码的改动极少。
462+ 借助适当的软件,计算可以分布在多个 GPU 上,无论是在单台服务器内还是跨集群。
513463
514464我们将在后续讲座中更详细地探讨 GPU 计算,并将其应用于一系列经济学应用。
0 commit comments