2016-03-26 8 views
2

私は並列処理が必要な画像処理の問題を扱っています。私は、Pythonでの並列処理の使用を示すいくつかの例を見てきましたが、これらすべての例の入力は1次元配列です。 したがって、画像上で2つのプロセスを実行する関数を並列化する方法を探しています。次のコードは、私が並列化する必要があるコードです:このPython for-loopをどのように並列化できますか?

for i in arange(0, shape(img)[0] - window_size[0], 10): 
    for j in arange(0, shape(img)[1] - window_size[1], 10): 
     Process1 = Do_something(img[i: i + winSize[0], j: j + winSize[1]]) 
     Process2 = Do_something(Process1) 

どのようにこのネストループを並列化できますか?

+0

はこれを見ている:https://www.quora.com/What-is-the-Python-equivalent-of-MATLABs-parfor – Swier

答えて

2

私は、変数を意味しています何かDo_something()機能がないん何を全くわからないが、これは、それを並列にする一般的な方法である:

import concurrent.futures 
import functools 

def process_stuff(i, j, img, winSize): 
    Process1 = Do_something(img[i: i + winSize[0], j: j + winSize[1]]) 
    Process2 = Do_something(Process1) 

with concurrent.futures.ProcessPoolExecutor() as executor: 
    for i in arange(0, shape(img)[0] - window_size[0], 10): 
     for j in arange(0, shape(img)[1] - window_size[1], 10): 
      executor.submit(process_stuff, i, j, img, winSize) 

このソリューションは、Pythonの3.2へと上に取り付けられています。古いバージョンではmultiprocessingモジュールを使用することがあります。

あなたも戻り値を取得することができ、より効率的な方法をご希望の場合は、これは別の方法です:

import concurrent.futures 
import functools 
import itertools 
import operator 

def process_stuff(i, j, img, winSize): 
    Process1 = Do_something(img[i: i + winSize[0], j: j + winSize[1]]) 
    Process2 = Do_something(Process1) 

with concurrent.futures.ProcessPoolExecutor() as executor: 
    i_iterator = arange(0, shape(img)[0] - window_size[0], 10) 
    j_iterator = arange(0, shape(img)[1] - window_size[1], 10) 
    product = itertools.product(i_iterator, j_iterator) 
    iter1, iter2 = itertools.tee(product) 
    i_iterator = map(operator.itemgetter(0), iter1) 
    j_iterator = map(operator.itemgetter(1), iter2) 

    do_process = functools.partial(process_stuff, img=img, winSize=winSize) 
    executor.map(do_process, i_iterator, j_iterator) 

それはもう少し複雑ですが、私はここでやったことのすべての組み合わせのproduct()を取得していますijと、2つのイテレータに分割されたijと、イテレータを変数とするmap()とに分割される。

UPDATE:

私の最善の策はあなたを保持する事が異なるプロセスへの画像の転送であるということです。 これは画像のみの適切な部分を転送します:

import concurrent.futures 
import itertools 

def process_stuff(img_part): 
    Process1 = Do_something(img_part) 
    Process2 = Do_something(Process1) 

with concurrent.futures.ProcessPoolExecutor() as executor: 
    i_iterator = arange(0, shape(img)[0] - window_size[0], 10) 
    j_iterator = arange(0, shape(img)[1] - window_size[1], 10) 
    product = itertools.product(i_iterator, j_iterator) 
    parts_generator = (img[i: i + winSize[0], j: j + winSize[1]] 
         for i, j in product) 

    executor.map(process_stuff, parts_generator) 
+0

おそらく、これはPython 3.2以降でのみ動作するというメモを追加するべきでしょう。 –

+0

@Bharel、あなたが私を助けてくれた時間にどうもありがとう。私は両方の形式のソリューションを使用しました。すべてのコアはプログラムの実行後に使用されますが、結果を出す時間はシングルコア処理よりもかなり長くなります。私はどこでミスをしていますか?ありがとうございます – Federico

+0

ありがとう@Federico :-)私は3番目のソリューションを提出しました。コードのどの部分に時間がかかるかを知るのは少し問題です。 'Do_something()'が長い時間がかかる関数で、並列に実行できる関数であれば、適切な画像部分を関数に渡すことで転送オーバヘッドが小さくなり、実行が速くなります。 – Bharel

関連する問題