1

Python 2.7.3 x64 wxPython 2.8 x64

Pythonのスレッド化とマルチプロセッシング、特にDougHellmannによるいくつかの記事をかなり読んでいます。しかし、私は1つのことについて混乱しています...

Pythonマルチプロセッシングモジュールは、引数が選択可能でなければならないことを除いて、多かれ少なかれスレッドモジュールのドロップイン代替品だと思いましたが、GUIをブロックしないために、最初に新しいスレッドを作成する必要があることがわかりましたthreading.Threadを使用してから、そのスレッド内でmultiprocessing.Processを使用してマルチプロセスを実行します。これは機能し、うまく機能しますが、私には少し厄介なようです。

最初にスレッド化せずに直接マルチプロセッシングを行おうとすると、マルチプロセッシングジョブが完了するまでGUIはブロックされます。それは設計どおりに機能していますか、それともマルチプロセッシングモジュールの基本的な何かが欠けていますか?

例が必要な場合は、提供できます。

ありがとう、

-RMWChaos

例がリクエストされました...

onProcess()がGUIのボタンによってトリガーされると仮定すると、これはGUIをブロックします...

import time
import multiprocessing as mp

def myWorker(a, b):
    time.sleep(0.1)
    print '{} * {} = {}'.format(a, b, a*b)

def onProcess(event):
    jobs = mp.cpu_count() * 2
    a = 5
    b = 10

    for job in range(jobs):
        mp.Process(target = myWorker, args = (a, b,)).start()

これはしませんが...

import time
import multiprocessing as mp
import threading as th

def myWorker(a, b):
    time.sleep(0.1)
    print '{} * {} = {}'.format(a, b, a*b)

def onProcess(event):
    a = 5
    b = 10
    th.Thread(target = myThread, args = [a, b,]).start()

def myThread(a, b):
    jobs = mp.cpu_count() * 2

    for job in range(jobs):
        mp.Process(target = myWorker, args = (a, b,)).start()
4

2 に答える 2

5

マルチスレッドとマルチプロセッシングは根本的に異なります。

ほとんどの場合、スレッドは i/o に使用されます。新しいスレッドを作成すると、スレッドを生成したプログラムと同じプロセス内に含まれます。つまり、メモリ空間をプログラムと共有しますが、それら (プログラムとスレッド) は並行して実行できません (GIL も検索します)。

一方、マルチプロセッシングは、OS レベルで新しいプロセスを生成します。この新しいプロセスは、既存のプロセスと並行して実行できますが、それを生成したプログラムとメモリ空間を共有しません。これは、高速化したいコードが I/O 関連ではなく、実際にプロセッサを集中的に使用する計算である場合に便利です。

GUI の場合、ほとんどの場合、GUI のさまざまな部分にスレッドを使用して、GUI の一部で何かを実行しても、その処理が終了するまで GUI 全体がロックされないようにする必要があります。

コードがないとわかりにくいですが、特に新しいスレッド内でプロセスを生成する必要はなく、そのスレッドが処理を処理するだけでよいと思います。ただし、そのスレッドが大量の I/O ではなく、集中的な計算タイプの処理を処理する必要がある場合は、それを処理するプロセスを開始する必要があります。

あなたの問題のほとんどは、マルチプロセッシングとマルチスレッドの誤解にあると思います。

于 2012-06-07T16:19:54.937 に答える
1

次のテストプログラムでコードを実行してみましたが、マルチプロセッシングは正常に機能し、何もブロックされません。

import time
import multiprocessing as mp
import wx


def myWorker(a, b):
    time.sleep(10)
    print '{} * {} = {}'.format(a, b, a*b)

def onProcess(event):
    jobs = mp.cpu_count() * 2
    a = 5
    b = 10

    for job in range(jobs):
        mp.Process(target = myWorker, args = (a, b,)).start()

def onGUI(event):
    print 'GUI is not blocked'

class MyFrame(wx.Frame):
    def __init__(self, parent, id, title):
       wx.Frame.__init__(self, parent, id, title)
       buttons = []
       panel = wx.Panel(self, wx.ID_ANY)
       sizer = wx.BoxSizer(wx.VERTICAL)
       gui_proc_btn = wx.Button(panel, wx.ID_ANY, 'GUI Process')
       other_proc_btn = wx.Button(panel, wx.ID_ANY, 'Other process')

       gui_proc_btn.Bind(wx.EVT_BUTTON, onGUI)
       sizer.Add(gui_proc_btn, 0, wx.ALL, 5)
       other_proc_btn.Bind(wx.EVT_BUTTON, onProcess)
       sizer.Add(other_proc_btn, 0, wx.ALL, 5)
       panel.SetSizer(sizer)

class MyApp(wx.App):
    def OnInit(self):
        frame = MyFrame(None, -1, 'test.py')
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

if __name__ == '__main__':

    app = MyApp(0)
    app.MainLoop()

これをコマンドラインから実行し、2番目のボタンを押して(これはmultiprocessing関数で使用され、スリープ時間を増やしました)、最初のボタンを押します。プログラムがブロックされないように、最初のボタンを押すと出力が生成されることに注意してください。

于 2012-06-07T17:28:47.100 に答える