2011-02-04 20 views
4

私はPythonスクリプトを用意しています。ハードコーディングされた入力ディレクトリに基づいて、すべての.mdbファイルをスキャンし、そのファイルをリストに入れてからforループ内ですべてを繰り返します。各反復には、複数のテーブル制限、結合、クエリなどが含まれます。Pythonを使用したArcGISでのマルチスレッド

唯一の問題...それは、入力データセット上で実行するのに約36時間を要し、このスクリプトはしかこの例では、このデータセットのために使用される一方で、私は多くの場合、編集フィールドの選択としての性能を向上したいと思い、私のスクリプトが非効率的であるため、時間がかかると言いたいのですが、ほぼすべての処理時間がジオプロセッサオブジェクト専用になっているため、非効率性は小さくなります。

私は私のメインのスクリプトに関連が持っているすべては、次のとおりです。

indir = "D:\\basil\\input" 
mdblist = createDeepMdbList(indir) 
for infile in mdblist: 
    processMdb(infile) 

順次実行するときにも完璧に実行されます。

私はパラレルのPythonを使って試してみました:

ppservers =() 
job_server = pp.Server(ppservers=ppservers) 

inputs = tuple(mdblist) 
functions = (preparePointLayer, prepareInterTable, jointInterToPoint,\ 
      prepareDataTable, exportElemTables, joinDatatoPoint, exportToShapefile) 
modules = ("sys", "os", "arcgisscripting", "string", "time") 

fn = pp.Template(job_server, processMdb, functions, modules) 
jobs = [(input, fn.submit(input)) for input in inputs] 

それは...、8つのプロセスを作成するために、8つのgeoprocessorオブジェクトを成功し、その後、失敗しました。

私はPythonのマルチスレッドツールを使って広範囲に実験をしていませんが、mdblistが表すキューを8つまでプロセスを生成するだけのガイダンスを期待していました。どの時点でも、同時に複数のプロセスがファイルの書き込みや読み取りを試みることはありません。一時的に物事を簡単にするために、私はこの問題のためにすべてのログツールを削除しました。私はこのスクリプトを実行して、わずかに異なるデータ形式を持つ4104の入力の4つのファイルを除いて動作することを知りました。

アドバイス? Arc Pythonスクリプトをマルチスレッド化しようとする知恵?

+1

があなたの代わりに、並列のpythonの組み込みの 'multiprocessing'モジュールを試してみましたか?これは、 'multiprocessing.Pool();と同じくらい単純でなければなりません。結果= pool.map(processMdb、filelist) '... ArcGISなどとはうまくいくはずですが、実際に試したことはありません。そして、Arcのバージョンのどれかが、 'multiprocessing'を持つのに十分な新しいバージョンのPythonを持っていれば、私は覚えていません。それはPython 2.6の標準ライブラリに入っただけです。 –

+0

申し訳ありませんが、バージョンを言及しているはずです...私は現在2.5にロックされているArc 9.3を使用しています。 2.6を得るためのいくつかの回避策がありますが、レポートは100%成功していません:[link](http://gis.stackexchange.com/questions/2226/can-i-use-python-2-6-with- arcgis-9-3)。 Arcmap 10は私には使えますが、2.6と一緒に出荷されますが、Pythonモジュールも変更されています。更新とテストが必要な古いスクリプトがたくさんあるので、私はアップグレードすることを躊躇しています。 @Joe – BasilV

+2

Python 2.5用のマルチプロセッシングのバックポートがあります:http://code.google.com/p/python-multiprocessing/標準ライブラリには存在しないいくつかの問題がありますしかし、2.6のバージョン...それは試してみる価値がある、と思います...幸運にも関係なく! –

答えて

5

私は私と私の経験のために働いたことを分かち合いました。

ジョーのコメントに従ってマルチプロセッシングモジュールのバックポート(code.google.com/p/python- multiprocessing)を使用するとうまくいきました。ローカル/グローバル変数とロギングを処理するためにスクリプト内でいくつか変更する必要がありました。

メインスクリプトは以下のようになります。

if __name__ == '__main__': 

    indir = r'C:\basil\rs_Rock_and_Sediment\DVD_Data\testdir' 
    mdblist = createDeepMdbList(indir) 

    processes = 6 # set num procs to use here 
    pool = multiprocessing.Pool(processes) 

    pool.map(processMdb, mdblist) 

合計時間6つのプロセスを使用して〜8まで〜36時間から行ってきました。

私が遭遇したいくつかの問題は、別々のプロセスを使用することによって、異なるメモリスタックに対処し、グローバル変数を完全に取り除くことでした。キューはこれに使用できますが、これを実装していないので、すべてがローカルで宣言されているだけです。

さらに、pool.mapは引数を1つしか取ることができないので、各反復では、8 gpを作成して各繰り返しに使用可能なものを渡すのではなく、ジオプロセッサオブジェクトを作成して削除する必要があります。各反復には約1分かかりますので、それを作成する数秒間は大したことではありませんが、それは加算されます。私は具体的なテストは行っていませんが、ArcGisとPythonで作業していた人は、ジオプロセッサがアクティブになっている時間が長いほどスクリプトが大幅に遅くなることを知っています(例えば、入力と時間の見積もりを過負荷にした作業者は、1時間の実行時間の50時間から2時間の実行後に800時間までの夜間の実行後350時間になりました。

誰かが大きなitterable入力を多重処理しようとするのに役立つだろうと思っています:)。次のステップ:再帰的な、多重処理された追加!

+0

+1 - すばらしいフォローアップ – radek

-1

同じ機能で上記の方法を比較しました。 結果:

Starting pp with 1 workers 
Time elapsed: 4.625 s 

Starting pp with 2 workers 
Time elapsed: 2.43700003624 s 

Starting pp with 4 workers 
Time elapsed: 2.42100000381 s 

Starting pp with 8 workers 
Time elapsed: 2.375 s 

Starting pp with 16 workers 
Time elapsed: 2.43799996376 s 

Starting mul_pool with 1 p 
Time elapsed: 5.31299996376 s 

Starting mul_pool with 2 
Time elapsed: 3.125 s 

Starting mul_pool with 4 
Time elapsed: 3.56200003624 s 

Starting mul_pool with 8 
Time elapsed: 4.5 s 

Starting mul_pool with 16 
Time elapsed: 5.92199993134 s 
関連する問題