在matplotlib中,我可以使用多个CPU来加速绘制许多子图和数据点吗?

时间:2017-01-02 23:46:59

标签: python matplotlib multiprocessing python-multiprocessing joblib

我正在创建一个包含大约一百个子图/轴的图形,每个图形具有几千个数据点。目前,我正在遍历每个子图并使用plt.scatter来放置点。但是,这很慢。是否可以使用多个CPU来加速绘图,通过将每个子图中的一个核心除以或在单个子图中绘制数据点进行划分?

到目前为止,我尝试使用joblib使用并行处理来创建子图,但是不是在同一图中创建新的子图,而是为每个子图生成一个新的图。我尝试使用后端PDFQt5AggAgg。这是我的代码的简化示例。

import matplotlib as mpl
mpl.use('PDF')
import seaborn as sns
import matplotlib.pyplot as plt
from joblib import Parallel, delayed

def plotter(name, df, ax):
    ax.scatter(df['petal_length'], df['sepal_length'])

iris = sns.load_dataset('iris')
fig, axes = plt.subplots(3,1)

Parallel(n_jobs=2)(delayed(plotter)
    (species_name, species_df, ax)
    for (species_name, species_df), ax in zip(iris.groupby('species'), axes.ravel()))

fig.savefig('test.pdf')

设置n_jobs=1有效,然后将所有点绘制在同一图中。但是,将其增加到1以上会产生四个数字:一个是我用plt.subplots启动的,然后是每次调用一个ax.scatter

由于我将轴从第一个图传递到plotter,我不确定如何/为什么要创建其他图形。在matplotlib中是否有一些回退,如果指定的数字被另一个绘图过程“锁定”,会导致自动创建新数字?

有关如何改进现有方法或通过替代方法实现加速的任何建议都表示赞赏。

1 个答案:

答案 0 :(得分:3)

Joblib的parallel使用multiprocessing模块生成进程,因此每个作业将在不同的进程中运行。这就是为什么你会得到每个工作的新数字。这些进程不像线程那样共享任何内存,因此他们无法访问原始数据。

你可能会尝试使用线程,但是由于全局解释器锁定(GIL),你是否会获得任何速度增加是值得怀疑的。

为了加快绘图速度,您可以尝试避免使用pyplot。它增加了一些开销和一个辅助线程,在每个绘图命令后重绘绘图。这主要是为了让例如ipython感觉更像Matlab - 但是对于速度来说这很糟糕。如果您只使用matplotlib,那么您可以选择仅在完成后绘制绘图,并且可能会节省相当长的时间。

注意:@Faultier在评论中提到您可以使用pyplot.ion()pyplot.ioff()启用和禁用交互式绘图。