zj3D 5 days ago
parent 129f1aaa3f
commit 4abad6851f

@ -2,7 +2,7 @@
从计算机系统结构的角度,提高 Python 任务执行速度的核心在于:减少解释器开销(编译/JIT、提升并行性多核/GPU、优化内存访问缓存友好、降低 I/O 瓶颈以及适配硬件特性等。当前主要办法如下:
### 计算单元层面利用多核并行计算
对于 CPU 密集型任务,使用多进程,每个进程拥有独立的 Python 解释器和内存空间运行在独立的内核上,实现并行计算。
对于 CPU 密集型任务,使用多进程,每个进程拥有独立的 Python 解释器和内存空间运行在独立的内核上,实现并行计算。
### I/O 层面减少等待时间
@ -12,30 +12,30 @@
### 编译层面减少解释器开销
- 使用 JIT 编译器Just-In-TimeJIT编译可以在运行时将Python代码编译成机器码从而提升执行速度 。PyPy 是一种替代 CPython 的实现,使用 JIT 技术,PyPy 的 JIT 引擎可以分析代码执行路径,优化频繁调用的函数,充分利用处理器架构。
- **Cython 编译**Cython 允许开发者为 Python 代码添加 C 类型注解,并编译为 C 代码,再由 C 编译器生成机器码。Cython 特别适合静态类型优化场景。
- 使用 JIT 编译器Just-In-TimeJIT编译可以在运行时将Python代码编译成机器码从而提升执行速度 。PyPy 是一种替代 CPython 的实现PyPy 的 JIT 引擎可以分析代码执行路径,优化频繁调用的函数,充分利用处理器架构。
- **Cython 编译**Cython 允许开发者为 Python 代码添加 C 类型注解,并编译为 C 代码,再由 C 编译器生成机器码。Cython 特别适合静态类型优化场景。
### 利用Python的解释器特性
- **使用内置数据类型和函数**:内置的数据类型(如列表、字典、集合等)和函数通常经过高度优化。
- **选择合适的数据结构**:例如,一些类型执行一些操作更快,一些类型更省空间
- **选择合适的数据结构**:例如,一些类型执行一些操作更快,一些类型更省空间
- **减少全局变量的使用**:访问全局变量通常比局部变量慢,因为它们需要在更大的作用域中查找。
- **减少函数调用**,可降低堆栈操作开销。
- 使用列表推导式替代循环追加,避免频繁创建和销毁临时对象的开销。
- 使用列表推导式替代循环,降低频繁创建和销毁临时对象的开销。
- 使用生成器而不是列表来处理大数据集,以减少内存占用。
- 使用XX池或预分配资源。
### 使用第三方高性能库
- NumPy、Pandas这些库用 C/C++ 编写并经过优化。
- NumPy 使用连续内存块存储数据向量化操作来代替显式的Python循环更高效 。
- SIMD 指令加速NumPy、Numba、Pandas/SciPy 都使用了SIMD。Cython 可以直接用 C 代码使用SIMD 。
- NumPy 使用连续内存块存储数据向量化操作来代替显式的Python循环更高效 。
- SIMD 指令加速NumPy、Numba、Pandas/SciPy 都使用了 SIMD。Cython 可以直接用 C 代码使用 SIMD 。
- `gzip` 模块可压缩数据,减少网络传输的数据量,提高网络传输速度。
- `mmap` 模块进行内存映射文件,处理超大文件、优化I/O性能以及进程间通信方面具有显著优势。
- `functools.lru_cache` 缓存计算结果,避免重复计算
- `mmap` 模块实现内存映射文件,在处理超大文件、优化I/O性能以及进程间通信方面具有显著优势。
- `functools.lru_cache` 缓存计算结果,避免重复计算 。
## 总结
具体实施时,应根据任务类型CPU 密集型、I/O 密集型或混合型)选择合适的优化策略,并结合性能分析工具(如 cProfile 、timeit或 line_profiler定位瓶颈。
计算设备方面的简单提升办法:使用多机、更快的 CPU、更多核的CPU、更多的内存、更快的存储、使用 GPU/FPGA/TPU 。
此外随着Python社区的发展新的技术和工具不断涌现开发者应持续关注最新进展,以便更好地优化自己的代 。
具体实施时,应根据任务特点选择合适的策略,并结合性能分析工具(如 cProfile 、timeit或 line_profiler定位瓶颈。
计算设备方面的简单提升办法:使用多机、更快的 CPU、更多核的CPU、更多的内存、更快的存储、增加 GPU/FPGA/TPU 。
此外随着Python社区的发展新的技术和工具不断涌现开发者应持续关注最新进展以便更好地优化自己的代

@ -1,27 +1,30 @@
### 内存管理
段:存放的是全局变量和静态变量
段:存放全局变量和静态变量
栈:系统自动分配释放,函数参数值,局部变量,返回地址等在此
堆:存放动态分配的数据,由开发人员自行管理
不同操作系统进程和线程实现机制有不同。
虚拟内存技术,把进程虚拟地址空间划分成用户空间和内核空间。
在 32 位操作系统中4GB 的进程地址中用户空间为 03G内核地址空间为 34G
在 32 位操作系统中4GB 的进程地址中用户空间为 03G内核地址空间为 34G
用户不能直接操作内核地址,只有通过系统调用的方式访问。
线程共享虚拟内存和全局变量等资源,线程拥有自己的私有数据比如栈和寄存器。
## 多任务
多任务就是操作系统可以同时运行多个任务。分为并行和并发两种。
多任务就是可以同时运行多个任务。分为并行和并发两种。
并行是真在不同CPU核上同时执行并发是轮换在一个核上执行。
## 阻塞/非阻塞
等候消息的过程中能不能干其他事
## 同步/异步
指的是消息通知的机制
一个任务完成后才能开始下一个任务是同步,
多个任务同时在运行状态是异步 。
通知调用者的三种方式,如下
状态:即监听被调用者的状态,调用者每隔一段时间检查一次是否完成(轮询)。
通知:当被调用者执行完成后,发出通知告知调用者。
@ -42,7 +45,7 @@
一个进程无法访问另一个进程的空间
一个进程运行的失败也不会影响其他进程的运行
因为操作系统可以切换进程,所以看起来同时运行的进程数会超过核数
因为操作系统可以切换进程,所以并发的进程数会超过核数
当需要创建的子进程数量巨大时,可以创建进程池
进程间常通过消息队列程序实现数据传递
@ -53,6 +56,6 @@
一个进程下的多个线程可以共享该进程的资源,包括内存。
多个线程同时对同一个全局变量操作,会出现竞争问题,从而数据结果会不正确
同步控制。某个线程要更改数据时,先将其锁定,直到将状态变成“非锁定”,其他的线程才能锁该资源。
解决办法:某个线程要更改数据时,先将其锁定,直到将状态变成“非锁定”,其他的线程才能锁该资源。
如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
可以用一些机制解决死锁,比如超时。

@ -1,19 +1,17 @@
Python的多线程时间切片间隔可以通过 sys.setswitchinterval() 设置。其他切换触发条件
- 当线程等待I/O操作如网络请求或磁盘读写GIL会被释放允许其他线程运行。
- 某些函数(如 time.sleep())会显式释放GIL切换到其他线程执行。
- 线程主动释放GIL
- 当线程等待I/O操作如网络请求或磁盘读写
- 某些函数(如 time.sleep())会触发切换
- 线程主动释放GIL
异步编程特别适合高并发的 I/O 密集型任务(如 Web 服务器、爬虫、实时通信), 特别是大量并发连接的任务。
对于 **I/O 密集型任务****异步编程** 通常比 **多线程** 是更好的选择。
多线程相对编程简单 。
异步编程通常比多线程控制更精细,但,多线程相对编程简单 。
以下场景更适合使用 **多线程**
### 场景:**GUI 应用程序**
在 GUI图形用户界面应用程序中主线程负责处理用户交互而其他任务如文件读写、网络请求需要在后台运行以避免阻塞主线程导致界面卡顿。多线程可以与 GUI 主线程共享内存,方便更新界面状态。线程间通信简单,适合处理后台任务。GUI 框架(如 PyQt、Tkinter通常有自己的事件循环与异步编程的事件循环冲突。
在 GUI图形用户界面应用程序中主线程负责处理用户交互而其他任务如文件读写、网络请求需要在后台运行以避免阻塞主线程导致界面卡顿。多线程可以与 GUI 主线程共享内存方便更新界面状态。线程间通信简单。GUI 框架(如 PyQt、Tkinter通常有自己的事件循环用异步编程容易冲突。
```python
@ -134,8 +132,8 @@ main()
### 场景:**任务队列与线程池**
在需要处理大量短期任务的场景中(如 Web 服务器的请求处理),使用线程池可以简单编程实现高效管理任务。
特别类似上面场景,有些任务是阻塞式的,不支持异步
在需要处理大量短期任务的场景中(如 Web 服务器的请求处理),使用线程池可以简单编程实现高效管理任务。
特别有些任务是阻塞式的,不支持异步
```python
import concurrent.futures
@ -186,42 +184,3 @@ def main():
main()
```
### 场景:**需要共享状态**
在某些场景中,多个任务需要频繁共享和修改状态(如缓存、计数器),使用多线程可以方便地共享内存。
线程之间可以直接访问和修改共享变量。
异步任务之间是独立的,不能直接共享变量或状态。
如果需要在任务之间共享状态,必须通过显式的机制(如队列、回调函数)来传递数据。
```python
import threading
class Counter:
def __init__(self):
self.value = 0
self.lock = threading.Lock()
def increment(self):
with self.lock:
self.value += 1
print(f"计数器值: {self.value}")
def worker(counter):
for _ in range(5):
counter.increment()
def main():
print("主线程开始")
counter = Counter()
# 创建多个线程共享计数器
threads = []
for i in range(3):
thread = threading.Thread(target=worker, args=(counter,))
thread.start()
threads.append(thread)
for thread in threads:
thread.join()
print("主线程结束")
main()
```

@ -18,6 +18,7 @@ JIT 的工作原理:**解释执行**:程序开始时,代码以解释方式
异步编程:异步编程是一种编程范式,允许任务并发执行。
在 Python 中,异步编程可以通过协程、回调、事件循环等多种方式实现。
异步编程适合高并发的 I/O 密集型任务(如 Web 服务器、爬虫、实时通信), 特别是大量并发连接的任务。
协程:协程是异步编程的一种实现方式,协程是一种在执行过程中可以暂停和恢复的函数。
协程运行在线程之上,协程的调度完全由用户控制 。

Loading…
Cancel
Save