对于大多数问题,并行计算确实可以提高计算速度。 随着PC计算能力的提高,我们可以通过在PC中运行并行代码来简单地提升计算速度。Joblib就是这样一个可以简单地将Python代码转换为并行计算模式的软件包,它可非常简单并行我们的程序,从而提高计算速度。
Joblib是一组用于在Python中提供轻量级流水线的工具。 它具有以下功能:
文档说明:https://joblib.readthedocs.io 下载地址:https://pypi.python.org/pypi/joblib#downloads 源码地址: https://github.com/joblib/joblib 报告问题:https://github.com/joblib/joblib/issues
pip install joblib
以下我们使用一个简单的例子来说明如何利用Joblib实现并行计算。 我们使用单个参数i
定义一个简单的函数my_fun()
。 此函数将等待1秒,然后计算i**2
的平方根,也就是返回i
本身。
from joblib import Parallel, delayed
import time, math
def my_fun(i):
""" We define a simple function here.
"""
time.sleep(1)
return math.sqrt(i**2)
这里我们将总迭代次数设置为10.我们使用time.time()
函数来计算my_fun()
的运行时间。 如果使用简单的for循环,计算时间约为10秒。
num = 10
start = time.time()
for i in range(num):
my_fun(i)
end = time.time()
print('{:.4f} s'.format(end-start))
10.0387 s
使用Joblib中的Parallel
和delayed
函数,我们可以简单地配置my_fun()
函数的并行运行。 其中我们会用到几个参数,n_jobs
是并行作业的数量,我们在这里将它设置为2
。 i
是my_fun()
函数的输入参数,依然是10次迭代。两个并行任务给节约了大约一半的for循环运行时间,结果并行大约需要5秒。
start = time.time()
# n_jobs is the number of parallel jobs
Parallel(n_jobs=2)(delayed(my_fun)(i) for i in range(num))
end = time.time()
print('{:.4f} s'.format(end-start))
5.6560 s
就是这么简单! 如果我们的函数中有多个参数怎么办? 也很简单。 让我们用两个参数定义一个新函数my_fun_2p(i,j)
。
def my_fun_2p(i, j):
""" We define a simple function with two parameters.
"""
time.sleep(1)
return math.sqrt(i**j)
j_num = 3
num = 10
start = time.time()
for i in range(num):
for j in range(j_num):
my_fun_2p(i, j)
end = time.time()
print('{:.4f} s'.format(end-start))
30.0778 s
start = time.time()
# n_jobs is the number of parallel jobs
Parallel(n_jobs=2)(delayed(my_fun_2p)(i, j) for i in range(num) for j in range(j_num))
end = time.time()
print('{:.4f} s'.format(end-start))
15.0622 s
除了并行计算功能外,Joblib还具有以下功能:
更多详情可参见Joblib官网。
Python函数的类似memoize或make的功能,适用于任意Python对象,包括非常大的numpy数组。通过将操作写成一组具有定义良好的输入和输出的步骤,将持久性和流执行逻辑与域逻辑或算法代码分离开来。Joblib可以节省他们的计算到磁盘和重新运行,只有在必要时。
>>> from joblib import Memory
>>> cachedir = 'your_cache_dir_goes_here'
>>> mem = Memory(cachedir)
>>> import numpy as np
>>> a = np.vander(np.arange(3)).astype(np.float)
>>> square = mem.cache(np.square)
>>> b = square(a) # doctest: +ELLIPSIS
________________________________________________________________________________
[Memory] Calling square...
square(array([[0., 0., 1.],
[1., 1., 1.],
[4., 2., 1.]]))
___________________________________________________________square - 0...s, 0.0min
>>> c = square(a)
>>> # The above call did not trigger an evaluation
参考:https://blog.csdn.net/qq_41185868/article/details/108278072 https://zhuanlan.zhihu.com/p/65025655