0

GDALオープンソースライブラリとそのライブラリで提供されるコマンドラインユーティリティを使用して、画像をタイリングするためのPythonスクリプトを作成しました。まず、各タイル範囲を示す入力データセットを読み取ります。次に、タイルをループし、サブプロセスを開始してgdalwarpを呼び出し、入力画像をループ内の現在のタイルにクリップします。

Popen.wait()を使用しないのは、タイルが同時に処理されないようにするためですが、サブプロセスによって返されたメッセージを追跡したいのです。さらに、特定のタイルの作成が完了したら、gdalinfoを使用して新しいファイルの統計を計算する必要があります。これには、別のサブプロセスが必要です。

コードは次のとおりです。

processing = {}
for tile in tileNums:
    subp = subprocess.Popen(['gdalwarp', '-ot', 'Int16', '-r', 'cubic', '-of', 'HFA', '-cutline', tileIndexShp, '-cl', os.path.splitext(os.path.basename(tileIndexShp))[0], '-cwhere', "%s = '%s'" % (tileNumField, tile), '-crop_to_cutline', os.path.join(inputTileDir, 'mosaic_Proj.vrt'), os.path.join(outputTileDir, "Tile_%s.img" % regex.sub('_', tile))], stdout=subprocess.PIPE)
    processing[tile] = [subp]

while processing:
    for tile, subps in processing.items():
        for idx, subp in enumerate(subps):
            if subp == None: continue
            poll = subp.poll()
            if poll == None: continue
            elif poll != 0:
                subps[idx] = None
                print tile, "%s Unsuccessful" % ("Retile" if idx == 0 else "Statistics")
            else:
                subps[idx] = None
                print tile, "%s Succeeded" % ("Retile" if idx == 0 else "Statistics")
                if subps == [None, None]:
                    del processing[tile]
                    continue
                subps.append(subprocess.Popen(['gdalinfo', '-stats', os.path.join(outputTileDir, "Tile_%s.img" % regex.sub('_',tile))], stdout=subprocess.PIPE))

ほとんどの場合、これは私にとってはうまくいきますが、私が見ている1つの問題は、最後のタイルに到達したときに無限ループを作成しているように見えることです。これが最善の方法ではないことはわかっていますが、私はサブプロセスモジュールに非常に慣れていないので、基本的にこれを一緒に投げて動作させようとしました。

タイルのリストをループし、同時に処理できるタイルごとにサブプロセスを生成し、タイルごとに最初のサブプロセスが完了したときに2番目のサブプロセスを生成するためのより良い方法を誰かが推奨できますか?

更新: これまでのすべてのアドバイスに感謝します。マルチプロセッシングモジュールとプールを利用するために、上記のコードをリファクタリングしようとしました。

新しいコードは次のとおりです。

def ProcessTile(tile):

    tileName = os.path.join(outputTileDir, "Tile_%s.img" % regex.sub('_', tile))

    warp = subprocess.Popen(['gdalwarp', '-ot', 'Int16', '-r', 'cubic', '-of', 'HFA', '-cutline', tileIndexShp, '-cl', os.path.splitext(os.path.basename(tileIndexShp))[0], '-cwhere', "%s = '%s'" % (tileNumField, tile), '-crop_to_cutline', os.path.join(inputTileDir, 'mosaic_Proj.vrt'), tileName], stdout=subprocess.PIPE)
    warpMsg = tile, "Retile %s" % "Successful" if warp.wait() == 0 else "Unsuccessful"

    info = subprocess.Popen(['gdalinfo', '-stats', tileName], stdout=subprocess.PIPE)
    statsMsg = tile, "Statistics %s" % "Successful" if info.wait() == 0 else "Unsuccessful"

    return warpMsg, statsMsg

print "Retiling..."
pool = multiprocessing.Pool()
for warpMsg, statsMsg in pool.imap_unordered(ProcessTile, tileNums): print "%s\n%s" % (warpMsg, statsMsg)

これは私にとっていくつかの大きな問題を引き起こしています。まず第一に、私は多くの新しいプロセスが作成されることになります。約半分はpython.exeで、残りの半分は、別のタイリングスキーム(gdalbuildvrt.exe)で既にタイリングされている場合に、受信画像をモザイク化するために上記のコードの前に呼び出す別のgdalユーティリティです。作成されているすべてのpython.exeプロセスとgdalbuildvrt.exeプロセスの間で、CPUの約25%(ハイパースレッドの場合は8コアのIntel I7)と16 GBのRAMの99%が使用され、コンピューターが完全にハングします。タスクマネージャーで、またはtaskkillを使用してコマンドラインからプロセスを強制終了することもできません。

ここで何が欠けていますか?

4

2 に答える 2

2

個々のサブプロセスを生成して管理する代わりに、python multiprocessingモジュールを使用してプロセスのプールを作成します。

于 2012-12-17T22:00:00.840 に答える
0

私はそれをテストしていませんが、動作するはずです:

import Queue

from threading import Thread

class Consumer(Thread):
    def __init__(self, queue=None):
        super(Consumer, self).__init__()

        self.daemon = True
        self.queue = queue


    def run(self):
        while True:
            task = self.queue.get()

            # Spawn your process and .wait() for it to finish.

            self.queue.task_done()

if __name__ == '__main__':
     queue = Queue.Queue()

     for task in get_tasks():
         queue.put(task)

     # You spawn 20 worker threads to process your queue nonstop
     for i in range(20):
         consumer = Consumer(queue)
         consumer.start()

     queue.join()

基本的に、実行する必要のあるタスクで満たされたキューがあります。次に、20個のワーカースレッドを生成して、キューから新しいタスクを継続的にプルし、それらを同時に処理します。

于 2012-12-17T22:03:26.373 に答える