Matplotlib 简明教程

Matplotlib - Multiprocessing

Multiprocessing 是一种用于并发执行多个进程的技术,利用了多核处理器。在 Python 中,multiprocessing 模块提供了一种便捷的方法来创建和管理并行进程。这对于可以并行化的任务很有用,例如生成图表、运行模拟或对大型数据集执行计算。

Multiprocessing in Matplotlib

Matplotlib 传统上以单线程方式使用,将其与多处理库结合使用可以并行创建图表。在处理大量图表或计算密集型任务时,这非常有用。

Creating Multiple Matplotlib Plots

按顺序创建多个图表会导致执行速度较慢,尤其是在处理大量图表时。在这种情况中,使用多处理技术可以通过允许并发创建多个图表来显著提高性能。

Example

让我们看一个基本示例,演示如何使用多处理并行创建多个 Matplotlib 图表。

import matplotlib.pyplot as plt
import numpy as np
import multiprocessing

def plot(datax, datay, name):
   x = datax
   y = datay**2
   plt.scatter(x, y, label=name)
   plt.legend()
   plt.show()

def multiP():
   for i in range(4):
      p = multiprocessing.Process(target=plot, args=(i, i, i))
      p.start()

if __name__ == "__main__":
   input('Press Enter to start parallel plotting...')
   multiP()

执行上述程序后,将并行创建 4 个 matplotlib 图表,请参阅下面的视频以获取参考 −

multiprocessing ex1

Saving Multiple Matplotlib Figures

并行保存多个 Matplotlib 图形是多处理可以发挥优势的另一个场景。

Example 1

这是一个使用多处理并行保存多个 Matplotlib 图形的示例。

import matplotlib.pyplot as plt
import numpy.random as random
from multiprocessing import Pool

def do_plot(number):
   fig = plt.figure(number)

   a = random.sample(1000)
   b = random.sample(1000)

   # generate random data
   plt.scatter(a, b)

   plt.savefig("%03d.jpg" % (number,))
   plt.close()

   print(f"Image {number} saved successfully...")

if __name__ == '__main__':
   pool = Pool()
   pool.map(do_plot, range(1, 5))

执行上述代码,我们将得到以下输出 −

Image 1 saved successfully...
Image 2 saved successfully...
Image 3 saved successfully...
Image 4 saved successfully...

如果您导航到保存图表的目录,您将能够看到 ved 001.jpg、002.jpg、003.jpg 和 004.jpg 图像,如下所示 −

multiprocessing ex2

Example 2

这是另一个演示如何使用多处理在一个进程中生成数据并在另一个进程中使用 Matplotlib 绘图的示例。

import multiprocessing as mp
import time
import matplotlib.pyplot as plt
import numpy as np

# Fixing random state for reproducibility
np.random.seed(19680801)

class ProcessPlotter:
   def __init__(self):
      self.x = []
      self.y = []

   def terminate(self):
      plt.close('all')

   def call_back(self):
      while self.pipe.poll():
         command = self.pipe.recv()
         if command is None:
            self.terminate()
            return False
         else:
            self.x.append(command[0])
            self.y.append(command[1])
            self.ax.plot(self.x, self.y, 'ro')
      self.fig.canvas.draw()
      return True

   def __call__(self, pipe):
      print('Starting plotter...')
      self.pipe = pipe
      self.fig, self.ax = plt.subplots()
      timer = self.fig.canvas.new_timer(interval=1000)
      timer.add_callback(self.call_back)
      timer.start()
      print('...done')
      plt.show()

class NBPlot:
   def __init__(self):
      self.plot_pipe, plotter_pipe = mp.Pipe()
      self.plotter = ProcessPlotter()
      self.plot_process = mp.Process(
         target=self.plotter, args=(plotter_pipe,), daemon=True)
      self.plot_process.start()

   def plot(self, finished=False):
      send = self.plot_pipe.send
      if finished:
         send(None)
      else:
         data = np.random.random(2)
         send(data)

# Main function for the integrated code
def main_with_multiprocessing():
   pl = NBPlot()
   for _ in range(10):
      pl.plot()
      time.sleep(0.5)
   pl.plot(finished=True)

if __name__ == '__main__':
   if plt.get_backend() == "MacOSX":
      mp.set_start_method("forkserver")
   input('Press Enter to start integrated example...')
   main_with_multiprocessing()

执行上述程序后,将使用随机数据生成 matplotlib 图表,请参阅下面的视频以获取参考 −

multiprocessing ex3