2011-08-26 12 views
41

最初に調べたところ、私の質問に対する答えが見つかりませんでした。私はPythonで複数の関数を同時に実行しようとしています。Python:どうすればPython関数を並列に実行できますか?

files.py 

import common #common is a util class that handles all the IO stuff 

dir1 = 'C:\folder1' 
dir2 = 'C:\folder2' 
filename = 'test.txt' 
addFiles = [25, 5, 15, 35, 45, 25, 5, 15, 35, 45] 

def func1(): 
    c = common.Common() 
    for i in range(len(addFiles)): 
     c.createFiles(addFiles[i], filename, dir1) 
     c.getFiles(dir1) 
     time.sleep(10) 
     c.removeFiles(addFiles[i], dir1) 
     c.getFiles(dir1) 

def func2(): 
    c = common.Common() 
    for i in range(len(addFiles)): 
     c.createFiles(addFiles[i], filename, dir2) 
     c.getFiles(dir2) 
     time.sleep(10) 
     c.removeFiles(addFiles[i], dir2) 
     c.getFiles(dir2) 

私は関数func1とfunc2のを呼び出して、それらを同時に実行したい:

私はこのような何かを持っています。関数は、相互に、または同じオブジェクト上で相互作用しません。今は、func1が終了するまでfunc1が終了するのを待たなければなりません。私は以下のような何かを行う方法:

process.py 

from files import func1, func2 

runBothFunc(func1(), func2()) 

は、私は同じ時間にかなり近い両方のディレクトリを作成することができるようにしたいので、すべての私は多くのファイルが作成されているか数えています分。ディレクトリがなければ、それは私のタイミングを捨てるでしょう。

+1

質問の更新 – lmcadory

+1

これを再設計することができます。毎分ファイル/フォルダの数を数えている場合、競合状態が発生しています。各関数がカウンタを更新するのはどうですか?または、ロックファイルを使用して、両方の関数の実行が完了するまで定期的なプロセスでカウントが更新されないようにしてください。 –

答えて

73

threadingまたはmultiprocessingを使用できます。

peculiarities of CPythonのために、threadingは真の並列性を達成する可能性は低いです。このため、一般的にはmultiprocessingが良い選択です。ここで

は完全な例である:

from multiprocessing import Process 

def func1(): 
    print 'func1: starting' 
    for i in xrange(10000000): pass 
    print 'func1: finishing' 

def func2(): 
    print 'func2: starting' 
    for i in xrange(10000000): pass 
    print 'func2: finishing' 

if __name__ == '__main__': 
    p1 = Process(target=func1) 
    p1.start() 
    p2 = Process(target=func2) 
    p2.start() 
    p1.join() 
    p2.join() 

子プロセスに参加/開始の仕組みは簡単runBothFuncの線に沿って機能にカプセル化することができます。

def runInParallel(*fns): 
    proc = [] 
    for fn in fns: 
    p = Process(target=fn) 
    p.start() 
    proc.append(p) 
    for p in proc: 
    p.join() 

runInParallel(func1, func2) 
+2

私はあなたのコードを使用しましたが、機能はまだ同時に起動しませんでした。 – lmcadory

+2

@Lamar McAdory:「同時に」とは、正確に何を意味するのかを説明してください。あなたがしたことの具体例、起こることを期待していたこと、そして実際に起こったことを教えてください。 – NPE

+3

@ラマー:「正確に同じ時間」を保証することは決してできません。あなたが持っているCPUの数、マシンの負荷、コンピュータ上で起こっている多くのことのタイミングは、すべてスレッド/プロセスの開始時間に影響します。また、プロセスは作成直後に開始されるため、プロセスの作成によるオーバーヘッドも、表示される時間差で計算する必要があります。 – Martin

3

に方法はありません2つの関数がお互いに同期して実行されることを保証します。これはあなたがしたいと思うものです。

あなたができることは、関数をいくつかのステップに分割し、@ aixの回答のようにProcess.joinを使用して重要な同期ポイントで終了するのを待つことです。

正確なタイミングを保証できないため、これはtime.sleep(10)よりも優れています。明示的に待機すると、10ms以内に実行されると仮定するのではなく、そのステップを実行する前にそのステップを実行しなければならないということですが、それはマシン上で何が行われているかに基づいて保証されません。

3

WindowsユーザーでPython 3を使用している場合、このポストはPythonで並列プログラミングを行うのに役立ちます。通常のマルチプロセッシングライブラリのプールプログラミングを実行すると、プログラムのmain関数に関するエラーが発生します。これは、ウィンドウにはfork()機能がないためです。以下の記事は、上記の問題に対する解決策を提供しています。

http://python.6.x6.nabble.com/Multiprocessing-Pool-woes-td5047050.html

Iは、Python 3を使用していたので、私は少しこのようなプログラムを変更:

:この関数の後

from types import FunctionType 
import marshal 

def _applicable(*args, **kwargs): 
    name = kwargs['__pw_name'] 
    code = marshal.loads(kwargs['__pw_code']) 
    gbls = globals() #gbls = marshal.loads(kwargs['__pw_gbls']) 
    defs = marshal.loads(kwargs['__pw_defs']) 
    clsr = marshal.loads(kwargs['__pw_clsr']) 
    fdct = marshal.loads(kwargs['__pw_fdct']) 
    func = FunctionType(code, gbls, name, defs, clsr) 
    func.fdct = fdct 
    del kwargs['__pw_name'] 
    del kwargs['__pw_code'] 
    del kwargs['__pw_defs'] 
    del kwargs['__pw_clsr'] 
    del kwargs['__pw_fdct'] 
    return func(*args, **kwargs) 

def make_applicable(f, *args, **kwargs): 
    if not isinstance(f, FunctionType): raise ValueError('argument must be a function') 
    kwargs['__pw_name'] = f.__name__ # edited 
    kwargs['__pw_code'] = marshal.dumps(f.__code__) # edited 
    kwargs['__pw_defs'] = marshal.dumps(f.__defaults__) # edited 
    kwargs['__pw_clsr'] = marshal.dumps(f.__closure__) # edited 
    kwargs['__pw_fdct'] = marshal.dumps(f.__dict__) # edited 
    return _applicable, args, kwargs 

def _mappable(x): 
    x,name,code,defs,clsr,fdct = x 
    code = marshal.loads(code) 
    gbls = globals() #gbls = marshal.loads(gbls) 
    defs = marshal.loads(defs) 
    clsr = marshal.loads(clsr) 
    fdct = marshal.loads(fdct) 
    func = FunctionType(code, gbls, name, defs, clsr) 
    func.fdct = fdct 
    return func(x) 

def make_mappable(f, iterable): 
    if not isinstance(f, FunctionType): raise ValueError('argument must be a function') 
    name = f.__name__ # edited 
    code = marshal.dumps(f.__code__) # edited 
    defs = marshal.dumps(f.__defaults__) # edited 
    clsr = marshal.dumps(f.__closure__) # edited 
    fdct = marshal.dumps(f.__dict__) # edited 
    return _mappable, ((i,name,code,defs,clsr,fdct) for i in iterable) 

を、上記の問題のコードは、ほとんどのように変更されます

from multiprocessing import Pool 
from poolable import make_applicable, make_mappable 

def cube(x): 
    return x**3 

if __name__ == "__main__": 
    pool = Pool(processes=2) 
    results = [pool.apply_async(*make_applicable(cube,x)) for x in range(1,7)] 
    print([result.get(timeout=10) for result in results]) 

そして私はのような出力を得た:

[1, 8, 27, 64, 125, 216] 

私は、この投稿が一部のWindowsユーザーには役立つと考えています。

関連する問題