ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

SciPy 并行执行支持完全指南:多线程、进程池、BLAS 线程控制与自由线程 Python

SciPy 并行执行支持完全指南:多线程、进程池、BLAS 线程控制与自由线程 Python SciPy 并行执行支持完全指南多线程、进程池、BLAS 线程控制与自由线程 Python【免费下载链接】scipySciPy library main repository项目地址: https://gitcode.com/gh_mirrors/sc/scipySciPy 在默认情况下采用单线程执行但在现代多核 CPU 与 GPU 环境中通过合理利用 BLAS/LAPACK 线程、workers参数、multiprocessing/threading以及实验性的自由线程 Pythonfree-threaded CPython与数组库后端如 PyTorch、CuPy、JAX可以显著提升计算效率。本文基于 parallel_execution.rst 的核心内容结合 SciPy 源码与测试系统讲解如何安全、有效地在 SciPy 中启用并行计算。一、SciPy 的并行默认行为单线程为主SciPy 的设计目标是提供高性能performant的计算功能但在并行策略上采取保守默认SciPy 自身默认单线程执行。绝大多数 SciPy 例程如统计、插值、信号处理等在默认配置下不会主动创建额外线程。唯一的例外是调用 BLAS/LAPACK 库的线性代数功能直接调用或经由 NumPy 间接调用。BLAS/LAPACK 库几乎总是默认多线程执行通常使用所有可用的 CPU 核心。这意味着当你执行矩阵乘法、特征值分解、SVD 等操作时即便你的 Python 代码是单线程的底层 BLAS 库如 OpenBLAS、MKL可能已经并行运行。二、控制 BLAS/LAPACK 线程数threadpoolctl由于 BLAS/LAPACK 的线程行为由底层库决定SciPy 用户可以通过threadpoolctl精确控制线程数。threadpoolctl是一个独立库可在不重新安装 NumPy/SciPy 的情况下在运行时动态设置线程数。基本用法from threadpoolctl import threadpool_limits with threadpool_limits(limits2, user_apiblas): # 这里的所有 BLAS/LAPACK 调用最多使用 2 个线程 result scipy.linalg.svd(matrix)limits目标线程数整数。user_apiblas作用于 BLAS/LAPACK 相关的 OpenBLAS、MKL、BLIS 等库。这在多用户共享服务器、或者你希望在进程内控制总线程数时尤其有用。三、逐 API 选择并行workers参数SciPy 在多个 API 中通过workers关键字提供选择性opt-in并行具体形式有两种整数指定使用的线程数或进程数。map 风格可调用对象例如multiprocessing.Pool用于进程池映射。3.1scipy.fft.fft线程池并行scipy.fft模块的所有 FFT 函数fft、ifft、rfft、fftn、rfftn、hfft等均支持workers参数import scipy.fft x np.random.randn(1000, 256, 256) y scipy.fft.fftn(x, workers4)根据 scipy/fft/_basic.py 的 docstringworkers : int, optional并行计算使用的最大 worker 数。若为负数则从os.cpu_count()环绕取值即workers-1表示使用所有 CPU 核心。具体地workers参数指定将 FFT 计算拆分成的最大并行任务数。它执行x中独立的 1-D FFT因此要求x至少是 2-D且非变换轴足够大以便切分。如果x太小实际使用的任务数可能少于请求数。3.2scipy.optimize.differential_evolution进程池并行differential_evolution支持workers的两种形式见 scipy/optimize/_differentialevolution.pyfrom scipy.optimize import differential_evolution def func(x): return sum(x**2) # 整数形式划分种群并用进程池并行评估 result differential_evolution(func, bounds[(-5, 5)] * 10, workers4) # map 风格可调用对象形式 from multiprocessing import Pool with Pool(4) as pool: result differential_evolution(func, bounds[(-5, 5)] * 10, workerspool.map)文档明确说明若workers为整数则种群被划分为workers个片段并行评估使用multiprocessing.Pool。workers-1使用所有可用 CPU 核心。也可以提供 map 风格可调用对象如multiprocessing.Pool.map评估以workers(func, iterable)方式执行。当workers ! 1时该选项会覆盖updating关键字为updatingdeferred并覆盖vectorized关键字。要求func可 picklepickleable因为要跨进程传递。注意使用进程池时每次评估都会产生进程间通信开销。对于快速函数进程开销可能超过并行收益对于耗时长的目标函数进程并行通常是更优选择。四、SciPy 内部的线程实现OS 线程池而非 OpenMP一个经常被误解的点是 SciPy 是否使用 OpenMP。根据文档和源码SciPy 内部的线程化使用 OS 级线程池OS-level thread pools。OpenMP 不用于 SciPy 内部。也就是说FFT 等功能的并行是在 SciPy 自身的 C/C 层通过线程池实现的而不是依赖 OpenMP 编译指示。这也意味着在开启 SciPy 并行时不需要考虑 OpenMP 环境变量如OMP_NUM_THREADS对 SciPy 内部的影响但需要注意它可能影响链接的 BLAS 库。五、multiprocessingvsthreading如何选择文档给出了明确的指导multiprocessing开销更高进程创建、IPC 序列化但广泛使用且稳健robust。适合 CPU 密集且目标函数较重、需要隔离全局状态或避免 GIL 的场景。threading开销更低在某些使用场景下有性能优势但必须阅读 thread_safety.rst 中的线程安全说明。关键背景来自 thread_safety.rstSciPy 支持通过标准库threading模块在多线程环境中使用。许多 SciPy 操作会释放 GILNumPy 也是如此SciPy 大量功能是对 NumPy 函数的调用——因此与 Python 中的许多其他情况不同在 Python 中利用多线程并行提升性能是可行的。5.1 线程安全的边界最容易获得性能提升的方式每个工作线程拥有自己的数组对象线程间不直接共享数据。大部分时间在底层代码释放 GIL中运行的线程通常会并行执行。可以在线程间共享 NumPy 数组但对共享数组进行原地修改mutating时必须格外小心。SciPy 函数不会修改用户传入的数组除非某个函数明确文档说明会这样做这种情况很少。因此对同一个 NumPy 数组以线程方式调用 SciPy 函数是安全的。有状态stateful的类需要更多注意scipy.integrate和scipy.interpolate中的一些积分与插值对象通常能接受并行调用或抛出信息性错误如scipy.integrate.ode对不支持并行执行的积分方法可能抛出IntegratorConcurrencyError。scipy.spatial.KDTree是线程安全的创建后没有修改接口可安全地从多个线程同时查询。scipy.sparse中的稀疏数组和矩阵是可变的当前不线程安全。尤其要避免在多个线程间共享时对数据结构进行原地修改如 item 或 slice 赋值可能导致数据损坏、崩溃或其他异常。若必须支持共享修改需自行加锁或避免共享修改。六、实验性支持一自由线程 Pythonfree-threaded CPythonSciPy 1.15.0 起配合 Python 3.13.0、NumPy 2.1.0SciPy 提供对free-threaded CPython 的实验性支持即禁用 GIL 的 CPython 构建。在自由线程 Python 中没有 GIL 来串行化对 Python 对象的访问线程间修改共享状态、产生线程安全问题的机会更多。所有 SciPy 功能都经过了并行线程使用的测试但仍预期存在尚未发现的问题。若遇到问题请检查 free-threading 标签的 issue 并提交新 issue。由于没有 GIL 限制之前不释放 GIL 的操作在 threading 下没有收益的限制在自由线程构建下不再适用参见 thread_safety.rst。七、实验性支持二非 NumPy 数组库后端PyTorch、CuPy、JAXSciPy 在越来越多的子模块和函数中提供对其他数组库PyTorch、CuPy、JAX的实验性支持。这类库默认并行执行可能带来显著的性能提升并支持 GPU 执行。这通常是通过 SciPy 的数组 API 支持机制实现的参见开发文档中的dev-arrayapi说明。相关基础设施可参考 scipy/_lib/_array_api.py 等实现。例如在支持数组 API 的函数中传入 CuPy 数组即可在 GPU 上执行import cupy as cp x cp.random.randn(1024, 1024) # 若函数支持数组 API 后端则该调用在 GPU 上运行注意FFT 等函数对workers参数在非 NumPy 后端下有额外校验。例如 scipy/fft/_basic_backend.py 中当使用非 NumPy 数组库后端时传入workers会抛出ValueErrorxp_unsupported_param_msg因为该参数在那些后端下不受支持。八、实战总结如何选择并行策略场景推荐方案理由线性代数为主matmul、SVD、eig 等调 BLAS 线程threadpoolctl底层 BLAS/LAPACK 已默认多线程大规模 FFT多维、轴可切分scipy.fft.fftn(..., workersn)内部 OS 线程池拆分独立 1-D FFT全局优化、耗时的目标函数differential_evolution(..., workersn)或pool.map进程级并行需目标函数可 pickleCPU 密集、无共享状态、许多例程释放 GILthreading低开销注意线程安全边界需要进程隔离、稳健性优先multiprocessing广泛使用、稳健但开销更高GPU 或大规模并行硬件CuPy/PyTorch/JAX 数组后端默认并行 GPU 执行实验性自由线程 CPython3.13构建 free-threaded 版本无 GIL 限制实验性SciPy 1.15九、相关资源官方并行执行教程doc/source/tutorial/parallel_execution.rst线程安全专题doc/source/tutorial/thread_safety.rstFFT 的workers参数实现scipy/fft/_basic.py差分进化并行实现scipy/optimize/_differentialevolution.py多线程测试scipy/fft/tests/test_multithreading.py数组 API 基础设施scipy/_lib/_array_api.py小结SciPy 的并行能力是一个分层体系——默认单线程、BLAS/LAPACK 自动多线程、workers选择性并行、multiprocessing/threading应用级并行再加上实验性的自由线程 Python 与多数组库后端。理解每一层的适用边界与线程安全约束是写出高效且健壮并行代码的关键。【免费下载链接】scipySciPy library main repository项目地址: https://gitcode.com/gh_mirrors/sc/scipy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表