2

Windows では、マルチプロセッシングを使用する前に、プロセスがメインかどうかを確認する必要があります。そうしないと、無限ループが発生します。

呼び出したクラスまたは関数内からマルチプロセッシングを使用するために、プロセスの名前をサブプロセスの名前に変更しようとしましたが、うまくいきませんでした。これは可能ですか?メインプロセスを使用していない限り、最新のマルチプロセッシングを使用できませんでした。

可能であれば、より高いプロセスから呼び出されているクラスまたは関数内でマルチプロセッシングを使用する方法の例を誰かが提供できますか? ありがとう。

編集:

ここに例があります - 最初のものは機能しますが、すべてが 1 つのファイルで行われます: simplemtexample3.py:

import random
import multiprocessing
import math

def mp_factorizer(nums, nprocs):
    #schtze den prozess
    #print __name__
    if __name__ == '__main__':
        out_q = multiprocessing.Queue()
        chunksize = int(math.ceil(len(nums) / float(nprocs)))
        procs = []
        for i in range(nprocs):

            p = multiprocessing.Process(
                    target=worker,            
                    args=(nums[chunksize * i:chunksize * (i + 1)],
                          out_q))
            procs.append(p)
            p.start()

        # Collect all results into a single result dict. We know how many dicts
        # with results to expect.
        resultlist = []
        for i in range(nprocs):
            temp=out_q.get()
            index =0
            #print temp
            for i in temp:
                resultlist.append(temp[index][0][0:])
                index +=1

        # Wait for all worker processes to finish
        for p in procs:
            p.join()
            resultlist2 = [x for x in resultlist if x != []]
        return resultlist2

def worker(nums, out_q):
    """ The worker function, invoked in a process. 'nums' is a
        list of numbers to factor. The results are placed in
        a dictionary that's pushed to a queue.
    """
    outlist = []

    for n in nums:
        newnumber= n*2
        newnumberasstring = str(newnumber)
        if newnumber:
            outlist.append(newnumberasstring)
    out_q.put(outlist)

l = []
for i in range(80):
    l.append(random.randint(1,8))

print mp_factorizer(l, 4)

ただし、別のファイルから mp_factorizer を呼び出そうとすると、if __name__ == '__main__'次の理由で機能しません。

simplemtexample.py

import random
import multiprocessing
import math

def mp_factorizer(nums, nprocs):
    #schtze den prozess
    #print __name__
    if __name__ == '__main__':
        out_q = multiprocessing.Queue()
        chunksize = int(math.ceil(len(nums) / float(nprocs)))
        procs = []
        for i in range(nprocs):

            p = multiprocessing.Process(
                    target=worker,            
                    args=(nums[chunksize * i:chunksize * (i + 1)],
                          out_q))
            procs.append(p)
            p.start()

        # Collect all results into a single result dict. We know how many dicts
        # with results to expect.
        resultlist = []
        for i in range(nprocs):
            temp=out_q.get()
            index =0
            #print temp
            for i in temp:
                resultlist.append(temp[index][0][0:])
                index +=1

        # Wait for all worker processes to finish
        for p in procs:
            p.join()
            resultlist2 = [x for x in resultlist if x != []]
        return resultlist2

def worker(nums, out_q):
    """ The worker function, invoked in a process. 'nums' is a
        list of numbers to factor. The results are placed in
        a dictionary that's pushed to a queue.
    """
    outlist = []

    for n in nums:
        newnumber= n*2
        newnumberasstring = str(newnumber)
        if newnumber:
            outlist.append(newnumberasstring)
    out_q.put(outlist)

単純なexample.pyを開始します

import simplemtexample as smt
import random

l = []
for i in range(80):
    l.append(random.randint(1,8))

print smt.mp_factorizer(l, 4)
4

2 に答える 2

2

if __name__ == '__main__'マルチプロセッシングを使用する場合は、(少なくとも Windows では) 必須です。

Windows では、次のように動作します。生成するワーカー スレッドごとに、Windows は自動的にメイン プロセスを開始し、必要なすべてのファイルを再び開始します。ただし、開始された最初のプロセスのみがmainと呼ばれます。これが、 で mt_factorizer の実行をブロックすることでif __name__ == '__main__'、マルチプロセッシングが無限ループを作成するのを防ぐ理由です。

したがって、基本的に Windows は、ワーカーを含むファイルと、ワーカーが呼び出すすべての関数をワーカーごとに読み取る必要があります。mt_factorizer をブロックすることで、追加のワーカーが作成されないようにしますが、ウィンドウは引き続きワーカーを実行できます。これが、すべてのコードが 1 つのファイルに含まれるマルチプロセッシングの例がワーカー (この場合は mt_factorizer のように) の作成を直接 (ワーカー関数ではなく) ブロックするため、Windows は引き続きワーカー関数を実行できます。すべてのコードが 1 つのファイルにあり、ファイル全体が保護されている場合、ワーカーは作成できません。

マルチプロセッシング コードが別のクラスにあり、呼び出される場合if __name__ == '__main__'は、呼び出しのすぐ上に実装する必要があります: mpteststart.py

import random
import mptest as smt

l = []
for i in range(4):
    l.append(random.randint(1,8))
print "Random numbers generated"
if __name__ == '__main__':
    print smt.mp_factorizer(l, 4)

mptest.py

import multiprocessing
import math

print "Reading mptest.py file"
def mp_factorizer(nums, nprocs):

    out_q = multiprocessing.Queue()
    chunksize = int(math.ceil(len(nums) / float(nprocs)))
    procs = []
    for i in range(nprocs):

        p = multiprocessing.Process(
                target=worker,            
                args=(nums[chunksize * i:chunksize * (i + 1)],
                      out_q))
        procs.append(p)
        p.start()

    # Collect all results into a single result dict. We know how many dicts
    # with results to expect.
    resultlist = []
    for i in range(nprocs):
        temp=out_q.get()
        index =0
        #print temp
        for i in temp:
            resultlist.append(temp[index][0][0:])
            index +=1

    # Wait for all worker processes to finish
    for p in procs:
        p.join()
        resultlist2 = [x for x in resultlist if x != []]
    return resultlist2

def worker(nums, out_q):
    """ The worker function, invoked in a process. 'nums' is a
        list of numbers to factor. The results are placed in
        a dictionary that's pushed to a queue.
    """
    outlist = []

    for n in nums:
        newnumber= n*2
        newnumberasstring = str(newnumber)
        if newnumber:
            outlist.append(newnumberasstring)
    out_q.put(outlist)

上記のコードでif __name__ == '__main__'は、呼び出し元ファイルに既にあるため、削除されています。

ただし、結果はやや予想外です。

Reading mptest.py file
random numbers generated
Reading mptest.py file
random numbers generated
worker started
Reading mptest.py file
random numbers generated
worker started
Reading mptest.py file
random numbers generated
worker started
Reading mptest.py file
random numbers generated
worker started
['1', '1', '4', '1']

マルチプロセッシングは無限実行からブロックされていますが、残りのコードはまだ数回実行されています (この場合は乱数生成)。これにより、パフォーマンスが低下するだけでなく、他の厄介なバグが発生する可能性があります。解決策は、マルチプロセッシングがどこかで使用されている場合、メインプロセス全体がウィンドウによって繰り返し実行されるのを防ぐことです: mptest.py

import random
import mptest as smt

if __name__ == '__main__':  
    l = []
    for i in range(4):
        l.append(random.randint(1,8))
    print "random numbers generated"   
    print smt.mp_factorizer(l, 4)

これで、返されるのは目的の結果だけです。乱数は一度だけ生成されます。

Reading mptest.py file
random numbers generated
Reading mptest.py file
worker started
Reading mptest.py file
worker started
Reading mptest.py file
worker started
Reading mptest.py file
worker started
['1', '6', '2', '1']

この例では、mpteststart.py がメイン プロセスであることに注意してください。そうでない場合はif __name__ == '__main__'、メイン プロセスになるまで呼び出しチェーンを上に移動する必要があります。メイン プロセスがそのように保護されると、不要なコード実行が繰り返されることはなくなります。

于 2013-01-30T10:46:44.743 に答える
1

窓がありませんos.forkそのため、Windows では、マルチプロセッシング モジュールが新しい Python インタープリターを開始し、 を呼び出すスクリプトを (再) インポートしますmultiprocessing.Process

を使用する目的は、スクリプトが再インポートされたときにif __name__ == '__main__'への呼び出しが再び呼び出されないようにすることです。multiprocessing.Process(守らないとフォークボムになる。)

スクリプトが再インポートされたときに呼び出されないmultiprocessing.Processクラスまたは関数内から呼び出している場合、問題はありません。先に進んで、通常どおり使用してください。multiprocessing.Process

于 2013-01-29T13:37:05.500 に答える