2016-06-14 13 views
2

私はシーケンシャルプログラムのために書いた関数を並列化しようとしています。 ["foo bar los angles", "foo bar new york", ...]マルチスレッドを使ってPythonで変数を(変更用ではなく)共有するには?

入力2、辞書のように文字列のリスト:["los angles", "new york"..]

私は入力1から入力2内のすべての文字列を削除したい以下は、入力および出力

入力1、文字列のリストです。出力は次のようになります:

["foo bar", "foo bar"]. 

私はダブルforループを使用してそれを行うことができます。

res = [] 
for s1 in input1: 
    for s2 in input2: 
     if s2 in s1: 
      res.append(s1.replace(s2, "")) 

しかし、これはリストINPUT1の200万サイズに少し遅い(私のMacBook Proの10分以上)を実行します(入力2は、数千人のカップルです)。

pythonのmultithreading.dummy.Poolを使用する方法が見つかりました。グローバル変数とともにpool.mapを使用して並列化します。しかし、私はグローバル変数の使用について懸念しています。それは安全ですか? Pythonマルチスレッドで変数を共有するための良い方法がありますか(apache sparkのmapPartionsのようなものかもしれません)?

私は現在Python 2.7を使用しています。だから私は答えpython2を使用することを好むだろう。

+2

並列化を進める前の中間段階として、リストをセットに切り替えるだけでコードをもっと速くすることができます(問題があれば問題あり) – Tyler

+0

元のリストの順序を保持する必要がありますか? – rrauenza

+0

@タイラー私はuse setがパフォーマンスを向上させるとは思わない。私はまだ全体のセットを横断する必要があるので。私の要件は、その部分文字列がinput2であれば、input1の項目の部分文字列を削除することです。だから私は使用セットがパフォーマンスを向上させるとは思わない。 – xuanyue

答えて

2

GILのためにパフォーマンスが必要な場合は、一般にマルチスレッドを避けることをおすすめします。幸いにも私たちはmultiprocessing

#!/usr/bin/python 
import itertools 
import multiprocessing 

in1 = ["foo bar los angles", "foo bar new york",] 
in2 = ["los angles", "new york",] 

results = [] 

def sub(arg): 
    s1, s2 = arg 
    if s2 in s1: 
     return s1.replace(s2, "") 

pool = multiprocessing.Pool(4) 
for result in pool.imap(sub, itertools.product(in1, in2)): 
    if result is not None: 
     results.append(result) 

print results 

あなた200万アイテムリストは、メモリ内に既にあるように聞こえるので、あなたは、何百万ものアイテムリストの数千人に物を回しから保つためにimapないmapを使用したいと思います。私はitertools.productを使って入力のデカルト積を行います。これは入れ子にされたループが行っていたものです。

あなたの要件は、一意性に関して少し曖昧でした。一致が見つかった場合は、結果に追加するだけでした。

本体にはresultsだけが追加されているので、グローバルresultsという変数については心配する必要はありません。 multithreadingを使用していた場合、map関数はGILの保護のために結果変数に直接書き込むことができますが、並行処理もGILに苦しんでいます。

imapを調整するには、大きいchunksizeを渡すことができます。 imap_unorderedを使用して注文した要件を緩和することで、さらに最適化することができます。詳細については、multiprocessingを参照してください。

+0

rrauenzeありがとうございます。しかし、ちょうどフォローアップの質問、私はfunction subのための別の入力を追加したいのですが?input1はlist [["foo bar los angles"]、["foo bar new york"]]のリストであり、内部変数にアクセスして文字列を取得するにはint変数0を渡す必要があるとします。それを共有するためにグローバル変数を使用しない方法はありますか? – xuanyue

+0

私はこのような質問を理解していません。投稿した質問を修正して、あなたがしたいことについてもっと正確にすることはできますか? – rrauenza

関連する問題