2013-08-15 5 views
10

私はORMとしてdjangoを使用するアプリケーションを作成しようとしています。これは、シーン処理の背後にあるものと使いやすいフロントエンドを行う必要があるためです。基本的な機能は、高CPUプロセス(基本的にはモンテカルロシミュレーション)でデータベースにあるデータを処理することです。具体的にはPool(4つのプロセスを取得)を使用してマルチプロセッシングを実装します。基本的に私のコードは、親の約20人の子供と、次のように実行します:Pythonマルチプロセスデータベースの並行処理、特にdjangoを扱うには?

assorted import statements to get the django environment in the script 
from multiprocessing import Pool 
from random import random 
from time import sleep 

def test(child): 
    x=[] 
    print child.id 
    for i in range(100): 
     print child.id, i 
     x.append(child.parent.id) #just to hit the DB 
    return x 

if __name__ == '__main__': 
    parent = Parent.objects.get(id=1) 
    pool = Pool() 
    results = [] 
    results = pool.map(test,parent.children.all()) 
    pool.close() 
    pool.join() 
    print results 

のようなコードでは、私はDatabaseError SまたはPicklingErrorの断続的な取得します。前者は通常 "不正な形式のデータベース"または "MySQLサーバーへの接続が失われた"形式であり、後者は通常 "pickleモデルではありません.DoesNotExist"です。それらはランダムであり、どのプロセスでも発生します。もちろん、DB自体には何も問題はありません。私がpool = Pool(proccesses=1)を設定すると、それは単なるスレッドでうまく動作します。私はまた、それらのほとんどが実際に実行されていることを確認するために様々な印刷ステートメントを投げます。

は、私はまたにtestを変更されています。ただ、各反復が実行する前に、秒未満を一時停止させ

def test(child): 
    x=[] 
    s= random() 
    sleep(random()) 
    for i in range(100): 
     x.append(child.parent.id) 
    return x 

、それはすべてがうまくなります。私が約500msまでランダムな間隔を取得すると、それは動作を開始します。ですから、並行性の問題でしょうか?しかし、4つのプロセスだけがヒットします。私の質問は、データの大量ダンプを事前に作成せずにこれをどのように解決するのですか?私はSQLiteとMySQLの両方でテストしており、どちらも問題があります。

+0

を、なぜデータベースへのすべての競合条件を避けるために 'multiprocessing.Lock'を使用しないでください。 – Bakuriu

答えて

7

だから、(友人の助けを借りて)問題は、djangoがすべてのプロセスで同じデータベース接続を使用していると判断したためです。通常、同時db要求がある場合、それらは同じスレッド(GILが起動)または別のスレッドにあります。その場合、djangoは異なるデータベース接続を行います。しかし、マルチプロセッシングでは、pythonはすべてのものをディープコピーしているので、同じデータベース接続をサブプロセスに渡してから、それらが壊れるまでお互いに歩いて行きます。

解決策は、各サブプロセス内から新しいdb接続をトリガーすることです(これは比較的高速です)。

from django import db 
... 
def sub_process(): 
    db.close_connection() 
    #the rest of the sub_process' routines 

#code that calls sub_process with the pool 

この行を持つことから前後して行き、その行を持たず、確かにすべてを修正します。

+1

ありがとう!私は以前にスレッドを使用していて、マルチプロセッシングの使用を開始したときに問題が発生しました。 2つのケースの間のあなたの説明は私の一日を作った。 – Mikuz

3

実際に私は最近、同じ問題を持っている、とこの記事を参照してください。Django multiprocessing and database connections ... とちょうどサブプロセスの接続閉鎖動作を呼び出す:プロセスがCPUバウンドなので

from django.db import connection 
connection.close()