0

我正在创建一个带有大约一百个子图/轴的图,每个子图都有几千个数据点。目前,我正在遍历每个子区域,并使用plt.scatter来放置点。但是,这很慢。是否可以使用多个CPU来加速绘图,通过将每个子图划分为一个核心还是绘制单个子图中的数据点?在matplotlib中,我可以使用多个CPU来加速绘制许多子图和数据点吗?

到目前为止,我曾尝试使用joblib为子图创建使用并行处理,但不是在同一图中创建新的子图,而是为每个子图生成一个新图。我已经尝试过后端PDF,Qt5AggAgg。这是我的代码的一个简单例子。

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中是否有一个回退,如果指定的数字被另一个绘图过程“锁定”,会自动创建新数字?

任何有关如何改善我目前的做法或通过替代方法实现加速的建议,我们感激不尽。

回答

2

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

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

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

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

+1

创建单独的数字,暂时保存并最终将它们加载到组合数字中可能最为可行?对于速度增益'plt.ioff()'也有帮助,因为避免了自动重绘。 – Faultier

+0

@Faultier @ J.P.Petersen谢谢!我已经在使用'plt.ioff'(不包括在问题的例子中,对不起),我从不显示这个图,只是创建它并保存为pdf。直接使用'matplotlib'还是避免使用'pyplot',我仍然可以获得显着的速度收益吗? –

+0

@Faultier你是指创建单独的数字并将它们合并的意思是什么?从[我读过](http://stackoverflow.com/questions/6309472/matplotlib-can-i-create-axessubplot-objects-then-add-them-to-a-figure-instance?noredirect=1&lq= 1),它很麻烦(如果可能的话),并且不正式支持分别创建matplotlib坐标轴并将它们组合在一个图中。你是指保存单独的PDF文件,然后将它们拼接在一起?我正在考虑这一点,但不知道哪一个是最好的跨平台(不幸的是我需要)python库来实现pdf拼接。 –

相关问题