ArcGISツールとして実行されるPythonスクリプトを高速化する方法[非公開]


31

これは非常に一般的な質問です。ツールボックスにインポートして実行するarcpyスクリプトを高速化するために、GISプログラマーがどのようなヒントとコツを使用したのかと思っています。

私はほとんど毎日、小さなスクリプトを書いて、オフィスの非GISユーザーがGISデータを処理できるようにしています。一般的に、ArcGIS 10.0の処理は9.3.1よりも遅く、Pythonスクリプトを実行するとさらに遅くなることがあります。

実行に24時間以上かかるスクリプトの特定の例をリストします。これは、バッファ内の各形状について、バッファ内のラスタの領域を集計するループです。バッファーには約7000の形状があります。私はそれがこれほど長く続くとは思わない。A

while x <= layerRecords:

    arcpy.SetProgressorLabel("Tabulating Row: " + str(x) + " of " + str(ELClayerRecords))
    arcpy.SelectLayerByAttribute_management(Buff,"NEW_SELECTION", "Recno = " + str(x))                                  # Selecting the record
    TabulateArea(Buff, "Recno", MatGRID, "VALUE", ScratchWS + "/tab" + str(z) +".dbf", nMatGRIDc)                          # Tabulate the area of the single row

    arcpy.AddMessage ("          - Row: " + str(x) + " completed")
    x = x + 1
    z = z + 1

誰かがそれを言う前に、私はバッファ全体で表領域を実行しましたが、複数のレコードで実行するとエラーが発生します。これは欠陥のあるツールですが、使用する必要があります。

とにかく、このスクリプトを最適化または高速化する方法についてアイデアをお持ちの方がいらっしゃれば幸いです。それ以外の場合、ArcGISで使用する場合、Pythonのスピードアップのトリックはありますか?

回答:


26

プロセスの高速化に役立つ可能性のある提案は次のとおりです。

  1. Select Layer By Attributeは、ArcGIS Desktopを起動することなく、Pythonのみのスクリプトに含めることができます。「バフ」参照をファイルベースの参照から「ArcGISレイヤー」参照に変換する必要があります。これは、ArcGISが選択クエリを処理できます。使用arcpy.MakeFeatureLayer_managementその後、あなたの「しばらく」ループ上記(「バフ」、「buff_lyr」)、および「buff_lyr」を使用するwhileループの下に、あなたの参照を変更。

  2. in_memoryワークスペースを使用して、できるだけ多くのGP操作を処理します ... arcpy.CopyFeatures_management(shapefile、 "in_memory \ memFeatureClass")を使用して、ソースをメモリに移動します。これは、必要なすべてのフィーチャクラスをメモリに読み込むのに十分なRAMがある場合にのみ有効です。ただし、in_memoryワークスペースを使用して実行できないGP操作がいくつかあることに注意してください(例:プロジェクトツール)。

ArcGIS 9.3オンラインヘルプ記事「中間データとスクラッチワークスペース」から(この言語は10.0および10.1ヘルプから削除されました):

注:in_memoryワークスペースに書き込むことができるのは、テーブルとフィーチャクラス(ポイント、ライン、ポリゴン)のみです。インメモリワークスペースは、サブタイプ、ドメイン、リプレゼンテーション、トポロジ、ジオメトリックネットワーク、ネットワークデータセットなどの拡張ジオデータベース要素をサポートしていません。簡単な機能とテーブルのみを記述できます。

ArcGIS 10.1オンラインヘルプ記事「メモリ内ワークスペースの使用」から:

インメモリワークスペースへの出力の書き込みを決定する際には、次の考慮事項を考慮する必要があります。

  • インメモリワークスペースに書き込まれるデータは一時的なものであり、アプリケーションが閉じられると削除されます。
  • テーブル、フィーチャクラス、およびラスターをインメモリワークスペースに書き込むことができます。
  • インメモリワークスペースは、サブタイプ、ドメイン、リプレゼンテーション、トポロジ、ジオメトリックネットワーク、ネットワークデータセットなどの拡張ジオデータベース要素をサポートしていません。
  • インメモリワークスペースでは、フィーチャデータセットまたはフォルダーを作成できません。

1
それは素晴らしいです!ArcMap以外で選択を使用する方法を探していましたが、これまでのところ成功していませんでした。この問題に関しては、実際には行ごとの時間を20秒から約13秒に押し下げました。しかし、私は他の手っ取り早い方法でループ内でMakeFeatureLayerを実行し、9秒になりました。これを行うには、フィーチャレイヤーから集計するよりも、各シェイプからフィーチャを作成しました。可能であれば、それをさらに引き下げたいと思っていますが、すでにはるかに高速なプロセスです!
コーディブラウン

#2で述べたように、CopyFeaturesを使用してソースデータin_memoryのコピーを作成し、in_memoryソースに対してfeature_layerを作成します。メモリへの最初のコピーにより、数秒前もって追加される場合がありますが、copyfeatures + tabulate_areasの処理により、現在のモデルよりも合計処理時間が速くなることがあります。
ライアンダルトン

私もそれを試しましたが、その解決策はループ処理を高速化するようですが、そうではありません。ループ内にフィーチャレイヤーを作成すると、ループごとに約8〜10秒かかりますが、ループの前にフィーチャレイヤーを作成すると、ループごとに11〜14秒になります。あなたのソリューションがより速く処理されるように聞こえるので、なぜ私はよくわかりません。私は8GBのRAMを持っているので、それが問題になるとは思わない。
コーディブラウン

また、ループの前にin_memoryに機能をコピーし、ループ内に機能レイヤーを作成すると、パフォーマンスがわずかに速くなります。ループごとに行ごとに8秒とほとんど変わりません。22に26時間から総処理時間をドロップしますどの
コーディ・ブラウン

あなたのアイデアを追加した後、私のスクリプトは劇的に改善されました。あなたと皆さんの助けに感謝します!
コーディブラウン

28

一般的なpython最適化手法を使用すると、かなりの時間を節約できます。

スクリプト内でホールドアップがどこにあるのかを把握するための本当に良いテクニックの1つは、組み込みのcProfileモジュールを使用することです。

from cProfile import run
run("code") # replace code with your code or function

小さなデータサンプルを使用してテストすると、どの関数呼び出しが最も時間がかかっているかを特定できます。

Pythonコードを高速化するための一般的なポインター:

  • リスト内包表記は一般にループよりも高速です
  • ジェネレータは、リスト全体を一度に作成するのではなく、一度に1つのアイテムを作成します
  • python 2ではrangeの代わりにxrangeを使用します(3では必要ありません)
  • アイテムがセットに存在するが、それは、その内容を反復処理することになると、一般的に遅くなるリストよりであれば、それは決定に来るときセットが出てプリフォームのリストをすることができますソース
  • 関数呼び出しパフォーマンスに負荷がかかる可能ありますSource
  • その他のヒントと詳細はこちらをご覧くださいPython Perfomance Tips and here 10 Python Optimization Tips and Issues

スクリプトに関しては、このコンピューターにArcがインストールされていないため、ArcPyの側面についてコメントすることはできませんが、whileループの代わりにforループを使用してみてください。また、x = x + 1はx + = 1として記述できます。

for record in layerRecords:
arcpy.SetProgressorLabel("Tabulating Row: " + str(x) + " of " + str(ELClayerRecords))
arcpy.SelectLayerByAttribute_management(Buff,"NEW_SELECTION", "Recno = " + str(x))                                  # Selecting the record
TabulateArea(Buff, "Recno", MatGRID, "VALUE", ScratchWS + "/tab" + str(z) +".dbf", nMatGRIDc)                          # Tabulate the area of the single row

arcpy.AddMessage ("          - Row: " + str(x) + " completed")
x+=1
y+=1

1
最後の箇条書きで残した2つのリンクを使用し、いくつかの簡単な修正でスクリプトを実際に支援することができました。
コーディブラウン

2つの正解を授与できれば、私はそうします。あなたの答えは本当にPythonを高速化する方法について多くのアイデアを提供しましたが、@ RyanDaltonは最もインパクトのあるアイデアを提供しました。トンありがとう!
コーディブラウン

13

コンピューターの内部ドライブに書き込みを行っていることを確認してください。必要のないときにネットワーク経由で到達すると、処理が本当に遅くなる可能性があります。プロセスの最初のステップとしてデータをコピーして、後続の読み取り/書き込みを可能な限り高速に保つこともより高速です。

ArcMapの完全に外部でスクリプトを実行すると、はるかに高速になります。処理中にマップが不要な場合は、ArcMapを使用しないでください。


ArcCatalogのモデル内で(Calculate Valueダイアログ内で単独で)スクリプトを実行すると、ArcMapのArcPyウィンドウから同じスクリプトを実行するよりも高速に処理されることがわかりました。しかし、それは純粋に逸話的な観察です。
シンディジャヤクマー

1
Tabulateが適切に機能するにはマップが必要だと思いますが、これを試してみます。ArcMapの外部で機能する場合は、速度が向上するはずです。また、ローカルディスクで既に実行しているため、スクリプトの速度は既に2倍になりました。
コーディブラウン

悲しいことに、選択はArcMapの外部では機能せず、図形ごとに表形式で行う必要があるため必要です。
コーディブラウン

3
@CodyBrown-ArcMapセッションの外部でSelectが機能しないというのは間違っています。MakeFeatureLayerツールの使用に関する私の回答をご覧ください。
ライアンダルトン

ライアンは正しい。選択ツールを単独で使用すると、空間データまたはテーブルデータのいずれかのテーブルビューが作成されます。ModelBuildeまたはスクリプトで使用する場合は、ビューを作成する必要があり、場合によってはMakeFeatureLayerツールを使用して作成する必要があります。
dchaboya

6

これは、ArcMap内でArcPyツールを実行するための質問には答えないかもしれませんが、ジオプロセシングツールとPythonで肉の処理を行う必要がある場合、IDE PyScripterを使用してGISシステムの外で実行する傾向があります。私はそれがより速く動くことを発見しました。また、小さな一時出力データセットにRAMDISKを使用しました(in_memoryワークスペースに少し似てます)

まあ、彼らは私の一番のヒントです!:)


2
Python IDEからスクリプトを実行するとき、この答えを多少濁らせるために、多くは変数の監視やその他のさまざまなデバッグ支援を支援するトレースバック関数を挿入します。この関数は、常に呼び出されるために実行しすぎるとスクリプトの速度が大幅に低下する可能性があり、ユーザーの介入なしに暗黙的にインストールされる場合もあります。ArcMapで実行されたPythonスクリプトが4分で実行され、Wing IDEからの同じスクリプトが3時間かかった特定の病理学的ケースがありました。WingなしでPython.exeから実行されるとすぐに、実行時の領域が2〜3分に戻りました。
ジェイソンシャイラー

1
ArMapでスクリプトを調整するのに頭痛がしていました。Pyscripterを使用するまで、最適化のヒントを使用せずにArcmapに比べて実行時間を大幅に短縮できる場合があります。
geogeek

@JasonScheirerは、これをオフにするWingの調整を見つけましたか?きっとあるはずです。
カーティス価格

5

arcpy.SetProgressorLabelをコメントアウトして、どれだけ高速化されるかを確認してください。私は、DOSのぼんやりした画面出力では、処理時間が大幅に遅くなることを発見しました。その出力を本当に見る必要がある場合は、N番目のループごとに表示してみてください。


4

import xxxx使用されていない行は必ず削除してください。

(つまりimport Math、まだ数学関数を使用していない場合は、スクリプトのロードから時間がかかります)

これは、実行する単一のスクリプト(ユーザーのスクリプトなど)には大きな影響を与えませんが、頻繁に繰り返し実行されるスクリプトには影響します。


7
標準のPythonモジュールがarcpyモジュールの初期化に要する時間の1000分の1以上を要するとは思いません。
-blah238

1
@ blah238 import Mathはおそらく悪い例でした。ただし、大規模なArcPyライブラリの中には、ロードにかなりの時間がかかるものがあります。
nagytech

1
これはまだ数時間ではなく、せいぜい数秒(最大で!)
マイクT

1
@MikeToews頻繁に繰り返し実行されるスクリプトの場合、数日/数週間などで数秒が加算されます。これはOPの主な問題を解決するものではありませんが、一般的なヒントを求めました。
nagytech
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.