2012-02-21 16 views
2

私はいくつかのコードをテストしています(速くしようとしていますが、違いを理解しようとしています)。私はメモリ内にテーブルを作成するループを持っています。私はそれから多重処理しようとしましたが、マルチプロセスではメモリ使用量が奇妙に見えます。私がそれを独自に実行すると、システム上のすべてのメモリが必要になるまでテーブルが成長し、成長し続けますが、マルチプロセッシングを使用すると時間がずっと低くなります。私は、マルチプロセッシングされていないコードを素早く作り直そうとしています。マルチプロセッシングで共有アイテムにメモリ制限がありますか?

ここではいくつかのコード(ちょうどそれがシステム・プロセスを確認するために速くまたは遅く走らせるために、データ変数から項目を追加/削除する多重処理がトップにあり、nonmultiは一番下にあります。)です:

from multiprocessing import Pool 
from multiprocessing.managers import BaseManager, DictProxy 
from collections import defaultdict 

class MyManager(BaseManager): 
    pass 

MyManager.register('defaultdict', defaultdict, DictProxy) 

def test(i,x, T): 
    target_sum = 1000 
    # T[x, i] is True if 'x' can be solved 
    # by a linear combination of data[:i+1] 
    #T = defaultdict(bool)   # all values are False by default 
    T[0, 0] = True    # base case 

    for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself 
      #print s 
      for c in range(s/x + 1): 
       if T[s - c * x, i]: 
        T[s, i + 1] = True 


data = [2,5,8,10,12,50]     
pool = Pool(processes=2) 
mgr = MyManager() 
mgr.start() 
T = mgr.defaultdict(bool) 
T[0, 0] = True 
for i, x in enumerate(data): # i is index, x is data[i] 
    pool.apply_async(test, (i,x, T)) 
pool.close() 
pool.join() 
pool.terminate() 


print 'size of Table(with multiprocesing) is:', len(T) 
count_of_true = [] 
for x in T.items(): 
    if T[x] == True: 
     count_of_true.append(x) 
print 'total number of true(with multiprocesing) is ', len(count_of_true) 


#now lets try without multiprocessing 
target_sum = 100 
# T[x, i] is True if 'x' can be solved 
# by a linear combination of data[:i+1] 
T1 = defaultdict(bool)   # all values are False by default 
T1[0, 0] = True    # base case 


for i, x in enumerate(data): # i is index, x is data[i] 
    for s in range(target_sum + 1): #set the range of one higher than sum to include sum itself 
      for c in range(s/x + 1): 
       if T1[s - c * x, i]: 
        T1[s, i + 1] = True 

print 'size of Table(without multiprocesing) is ', len(T1) 

count = [] 
for x in T1: 
    if T1[x] == True: 
     count.append(x) 

print 'total number of true(without multiprocessing) is ', len(count) 
は、

実験として、私は両方のコードを2つのファイルに入れ、それらを並べて走らせました。 2つのマルチは約20%を占め、メモリの0.5%しか使用しません。単一プロセス(マルチなし)は、コアの75%と最大50%のメモリ使用量を使用しています。

+0

あなたは次のように書いています: "自分でそれを実行すると..."あなたはPool(processes = 1)の設定について話しますか? – itsafire

+0

正確ではありません。私のコードでは、私は2つのセクションを持っています.1つはマルチプロセスプールにラップされ、もう1つはプールなしで実行されます。 – Lostsoul

答えて

2

私があなたのコードを正しく理解していれば、本当の問題はマルチプロセッシングでルックアップテーブルを構築できないことです。

この:あなたは他の後にitoneステップをやっているので、

for i, x in enumerate(data): 
    for s in range(target_sum + 1): 
     for c in range(s/x + 1): 
      if T1[s - c * x, i]: 
       T1[s, i + 1] = True 

が働きます。この一方で

:あなたはRecursivelyListAllThatWork()のように、あなたの新しいものを構築するためにあなたの前の結果を必要とするbeacuse

def test(i,x, T): 
    target_sum = 1000 
    T[0, 0] = True 
    for s in range(target_sum + 1): 
     for c in range(s/x + 1): 
      if T[s - c * x, i]: 
       T[s, i + 1] = True 

# [...] 

for i, x in enumerate(data): 
    pool.apply_async(test, (i,x, T)) 

は、同じことを行うことはありません。

for x in T: 
    if T[x] == True: 
     count_of_true.append(x) 

をそして、それもあなたの場合、あなたドンでも、==でないisTrueを比較すると良いでしょう:

for x in T.items(): 
    if T[x] == True: 
     count_of_true.append(x) 

は次のようになります。

これは、またあなたのカウントのバグがありますその必要がない:

for x in T: 
    if T[x]: 
     count_of_true.append(x) 

Iothersはすでにあなたに語っているので、副題として実際にはdefaultdictは必要ありません。

+0

しかし、プロセス= 1であっても、マルチプロセッシングなしでは完全にメモリを消耗しません。私は別のマルチプロセスを使って同じことに気付きました(シングルプロセスはメモリが急増しますが、マルチは単一のポイントを超えて成長しないように見えます)。 – Lostsoul

+0

@ロストソウル:私はそれが重要だとは思わない。問題はforループですべてのテーブルを繰り返し実行していることです。私はあなたのコードを実行して、マルチプロセッシングテーブルはない場合よりも約10倍大きくなります。複数のテーブルの代わりに1つの共有テーブルを使用していたために使用された可能性のあるメモリ使用量について、ここでは説明しません。 –

+0

しかし、マルチプロセッシングでは、(マルチを使わずに)1つの共有テーブルが存在するのではなく、独自のバージョンのテーブルで作業していて、それをマスターなどと同期させるべきですか?申し訳ありませんが、私はまだメモリの違いを理解していません。また、あなたの更新された回答を読んでいます。 – Lostsoul

関連する問題