Matplotlib - 多程序



多程序是一種用於併發執行多個程序的技術,利用多核處理器。在 Python 中,multiprocessing 模組提供了一種方便的方式來建立和管理並行程序。這對於可以並行化的任務很有用,例如生成繪圖、執行模擬或對大型資料集執行計算。

Matplotlib 中的多程序

Matplotlib 傳統上以單執行緒方式使用,將其與 multiprocessing 庫結合使用可以並行建立繪圖。這在處理大量繪圖或計算密集型任務時很有用。

建立多個 Matplotlib 繪圖

順序建立多個繪圖會導致執行速度變慢,尤其是在處理大量繪圖時。在這種情況下,使用多程序技術可以透過允許併發建立多個繪圖來顯著提高效能。

示例

讓我們來看一個基本示例,演示如何使用多程序並行建立多個 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

儲存多個 Matplotlib 圖形

併發儲存多個 Matplotlib 圖形是多程序可以發揮優勢的另一種場景。

示例 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

示例 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 GIF
廣告