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

Python 在matplotlib中,我可以使用多个CPU来加速绘制多个子地块和数据点吗?,python,matplotlib,multiprocessing,python-multiprocessing,joblib,Python,Matplotlib,Multiprocessing,Python Multiprocessing,Joblib,我正在创建一个图形,其中包含大约100个子地块/轴,每个子地块/轴包含数千个数据点。目前,我正在遍历每个子地块,并使用plt.scatter放置点。然而,这是相当缓慢的。是否可以使用多个CPU来加速绘图,方法是将人工划分为每个子批次一个核心,或在单个子批次内绘制数据点 到目前为止,我已经尝试使用joblib为子地块创建使用并行过程,但它不是在同一个图形中创建新的子地块,而是为每个子地块生成一个新图形。我试过使用后端PDF,Qt5Agg和Agg。下面是我的代码的一个简化示例 import matp

我正在创建一个图形,其中包含大约100个子地块/轴,每个子地块/轴包含数千个数据点。目前,我正在遍历每个子地块,并使用
plt.scatter
放置点。然而,这是相当缓慢的。是否可以使用多个CPU来加速绘图,方法是将人工划分为每个子批次一个核心,或在单个子批次内绘制数据点

到目前为止,我已经尝试使用
joblib
为子地块创建使用并行过程,但它不是在同一个图形中创建新的子地块,而是为每个子地块生成一个新图形。我试过使用后端
PDF
Qt5Agg
Agg
。下面是我的代码的一个简化示例

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启动的。子图
,然后每次调用一个
ax.scatter

由于我将轴从第一个图形传递到
绘图仪
,因此我不确定如何/为什么创建其他图形。matplotlib中是否存在一些回退,如果指定地物被另一个打印过程“锁定”,则会导致自动创建新地物


任何关于如何改进当前方法或通过其他方法实现加速的建议,我们都将不胜感激。

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

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

为了加快打印速度,您可以尝试避免使用
pyplot
。它增加了一些开销和一个助手线程,该线程在每个打印命令后重新绘制打印。这主要是为了让ipython感觉更像Matlab,但对于速度来说这是不好的。如果仅使用
matplotlib
,则可以选择仅在完成绘图后绘制绘图,这可能会节省大量时间


注意:@Faultier在一条评论中提到,您可以使用
pyplot.ion()
pyplot.ioff()
Joblib的
parallel
使用
多处理
模块生成进程,因此每个作业将在不同的进程中运行。这就是为什么每项工作你都会得到一个新的数字。这些进程不像线程那样共享任何内存,因此它们无法访问原始图形

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

为了加快打印速度,您可以尝试避免使用
pyplot
。它增加了一些开销和一个助手线程,该线程在每个打印命令后重新绘制打印。这主要是为了让ipython感觉更像Matlab,但对于速度来说这是不好的。如果仅使用
matplotlib
,则可以选择仅在完成绘图后绘制绘图,这可能会节省大量时间


注意:@Faultier在一条评论中提到,您可以使用
pyplot.ion()
pyplot.ioff()

启用和禁用交互式绘图。创建单独的图形,临时保存它们,最后将它们加载到组合图形中,这可能是最切实可行的方法?对于速度增益
plt.ioff()
也有帮助,因为避免了自动重画。@Faultier@J.P.Petersen谢谢!我已经在使用
plt.ioff
(对不起,问题中的示例中没有包含),我从不显示图形,只是创建它并另存为pdf。直接使用
matplotlib
并完全避免使用
pyplot
是否仍能显著提高速度?@Faultier创建单独的图形并将其组合是什么意思?从什么角度来看,单独创建matplotlib轴并将它们组合在一个图形中既麻烦又不受官方支持。您是指保存单独的PDF然后将它们缝合在一起吗?我正在考虑这一点,但不确定哪一个是实现pdf缝合的最佳跨平台python库。@J.P.Petersen我仍然不完全清楚为什么会创建不同的图形。我知道作业在不同的进程中运行,这意味着如果在一个进程中创建了某些内容,那么其他同时运行的进程将无法访问该内容。但是,我在生成进程之前创建图形,并将现有轴传递给每个进程。难道他们不能访问这个在进程生成之前创建的特定轴吗?@cheflo每个子进程在生成之前都会有一个图形轴和所有其他变量的副本-但是如果对内存进行了任何修改,通常只会对子进程进行修改。这通常称为写时复制()。您可以尝试将轴从
plotter()
函数返回到父进程,但我怀疑它是否有效。Matplotlib声明一个轴只能属于一个图形。创建单独的图形、临时保存它们并最终将它们加载到组合图形中可能是最可行的?对于速度增益
plt.ioff()
也有帮助,因为避免了自动重画。@Faultier@J.P.Petersen谢谢!我已经在使用
plt.ioff
(对不起,问题中的示例中没有包含),我从不显示图形,只是创建它并另存为pdf。我还会继续吗