以前のバージョンと比較して、データアクセスカーソルのパフォーマンスはどのように向上していますか?


18

データアクセスモジュールは、ArcGISバージョン10.1で導入されました。ESRIは、データアクセスモジュールを次のように記述します(ソース):

データアクセスモジュールarcpy.daは、データを操作するためのPythonモジュールです。編集セッションの制御、編集操作、改善されたカーソルサポート(高速パフォーマンスを含む)、テーブルとフィーチャクラスのNumPy配列との変換、バージョン管理、レプリカ、ドメイン、サブタイプのワークフローのサポートが可能になります。

ただし、カーソルのパフォーマンスが以前の世代のカーソルよりも向上した理由に関する情報はほとんどありません。

添付の図は、新しいdaメソッドUpdateCursorと古いUpdateCursorメソッドのベンチマークテストの結果を示しています。基本的に、スクリプトは次のワークフローを実行します。

  1. ランダムポイント(10、100、1000、10000、100000)を作成します
  2. 正規分布からランダムにサンプリングし、カーソルを使用してランダムポイント属性テーブルの新しい列に値を追加します
  3. 新しいUpdateCursorメソッドと古いUpdateCursorメソッドの両方について、各ランダムポイントシナリオを5回繰り返し、平均値をリストに書き込みます
  4. 結果をプロットする

daカーソルのパフォーマンスを図に示されている程度まで改善するために、更新カーソルを使用して舞台裏で何が行われていますか?


ここに画像の説明を入力してください


import arcpy, os, numpy, time
arcpy.env.overwriteOutput = True

outws = r'C:\temp'
fc = os.path.join(outws, 'randomPoints.shp')

iterations = [10, 100, 1000, 10000, 100000]
old = []
new = []

meanOld = []
meanNew = []

for x in iterations:
    arcpy.CreateRandomPoints_management(outws, 'randomPoints', '', '', x)
    arcpy.AddField_management(fc, 'randFloat', 'FLOAT')

    for y in range(5):

        # Old method ArcGIS 10.0 and earlier
        start = time.clock()

        rows = arcpy.UpdateCursor(fc)

        for row in rows:
            # generate random float from normal distribution
            s = float(numpy.random.normal(100, 10, 1))
            row.randFloat = s
            rows.updateRow(row)

        del row, rows

        end = time.clock()
        total = end - start
        old.append(total)

        del start, end, total

        # New method 10.1 and later
        start = time.clock()

        with arcpy.da.UpdateCursor(fc, ['randFloat']) as cursor:
            for row in cursor:
                # generate random float from normal distribution
                s = float(numpy.random.normal(100, 10, 1))
                row[0] = s
                cursor.updateRow(row)

        end = time.clock()
        total = end - start
        new.append(total)
        del start, end, total
    meanOld.append(round(numpy.mean(old),4))
    meanNew.append(round(numpy.mean(new),4))

#######################
# plot the results

import matplotlib.pyplot as plt
plt.plot(iterations, meanNew, label = 'New (da)')
plt.plot(iterations, meanOld, label = 'Old')
plt.title('arcpy.da.UpdateCursor -vs- arcpy.UpdateCursor')
plt.xlabel('Random Points')
plt.ylabel('Time (minutes)')
plt.legend(loc = 2)
plt.show()

回答:


25

arcpy.daここの開発者の一人。パフォーマンスが主な関心事であったため、パフォーマンスを得ました。古いカーソルの主な不満は、特定の機能が欠けていることではなく、遅いことでした。コードは、8.x以降のArcGISで使用可能な同じ基になるArcObjectsを使用します(たとえば、検索カーソルのCPython実装は、C#ではなくC ++を除き、実装ではこのようなコードサンプルによく似ています)。

したがって、高速化を実現するために行った主な2つのことは次のとおりです。

  1. 抽象化層の排除: Pythonカーソルの初期実装は、古いDispatch / COMベースのGPDispatchオブジェクト基づいていたためCOM Dispatchオブジェクトを使用できる任意の言語で同じAPIを使用できました。これは、単一の環境に特に最適化されていないAPIがあったことを意味しますが、たとえば、実行時にメソッドをアドバタイズおよび解決するためのCOMオブジェクトの抽象化レイヤーが多数あったことも意味します。ArcGIS 9.3より前のバージョンを覚えていれば、同じ不格好なインターフェイスを使用して、PerlやRubyなどの多くの言語でジオプロセシングスクリプトを作成することができました。オブジェクトが処理するために必要な追加の書類IDispatch ものは、関数呼び出しに多くの複雑さとスローダウンを追加します。
  2. Pythonのイディオムとデータ構造を使用して、緊密に統合されたPython固有のC ++ライブラリを作成Rowます。オブジェクトのアイデアと本当に奇妙なwhile cursor.Next():ダンスは、Pythonでは単純に非効率的でした。リストからアイテムを取得するのは非常に高速な操作であり、CPython関数呼び出し(基本的に__getitem__は、リストで大幅に最適化された呼び出し)を2、3個まで単純化します。row.getValue("column")比較によって行うことはより重いです:__getattr__メソッド(新しいバインドメソッドオブジェクトを作成する必要があるメソッド)をフェッチし、指定された引数(__call__)でそのメソッドを呼び出します。arcpy.da実装の各部分はCPython APIと非常に密接に統合されています ネイティブPythonデータ構造を使用して、手作業で調整された多くのC ++を使用して高速化します(さらに、速度とメモリ効率を高めるためにnumpy統合も使用します)。

また、ほぼすべてのベンチマーク(たとえばこれらのスライドを参照)で、.NetおよびC ++のarcobjectsはarcpy.da、ほとんどのタスクの2倍以上の速度であることに気付くでしょう。Pythonコードの使用arcpy.daは高速ですが、コンパイル済みの低レベル言語よりも高速ではありません。

TL; DRはdaので、高速でda具体速いPythonコードをもたらすように設計された直アップ、純粋のArcObjects / C ++ / CPythonのに実装されています。


4

パフォーマンス関連

  • カーソルは、デフォルトではフィールドのセットリストを反復します(データベース全体ではありません)

その他、パフォーマンスに直接関係しないが、素晴らしい機能強化:

  • フィーチャジオメトリにアクセスするためにトークン(例:SHAPE @ LENGTH、SHAPE @ XY)を使用する機能
  • データベースをウォークスルーする機能arcpy.da.Walkメソッドを使用)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.