이전 버전에 비해 데이터 액세스 커서 성능이 어떻게 향상 되었습니까?


18

데이터 액세스 모듈은 ArcGIS 버전 10.1에서 도입되었습니다. ESRI는 데이터 액세스 모듈을 다음과 같이 설명합니다 ( source ).

데이터 액세스 모듈 arcpy.da는 데이터 작업을위한 Python 모듈입니다. 편집 세션, 편집 작업, 향상된 커서 지원 (보다 빠른 성능 포함), 테이블 및 기능 클래스를 NumPy 배열로 변환하는 기능, 버전 관리, 복제본, 도메인 및 하위 유형 워크 플로를 지원합니다.

그러나 왜 커서 성능이 이전 세대의 커서보다 향상되었는지에 대한 정보는 거의 없습니다.

첨부 된 그림은 새 da메소드 UpdateCursor와 이전 UpdateCursor 메소드 에 대한 벤치 마크 테스트 결과를 보여줍니다 . 기본적으로 스크립트는 다음 워크 플로우를 수행합니다.

  1. 랜덤 포인트 생성 (10, 100, 1000, 10000, 100000)
  2. 정규 분포에서 무작위로 표본을 추출하고 커서를 사용하여 무작위 점 속성 테이블의 새 열에 값을 추가합니다
  3. 신규 및 기존 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에서 사용할 수있는 동일한 기본 ArcObject를 사용합니다 (예를 들어, 검색 커서의 CPython 구현은 구현 에서 C # 대신 C ++을 제외하고 는 이와 유사한 코드 샘플과 유사 함 ).

속도 향상을 위해 우리가 한 두 가지 주요 사항은 다음과 같습니다.

  1. 추상화 계층 제거 : Python 커서의 초기 구현은 이전 Dispatch / COM 기반 GPDispatch 객체를 기반으로 하므로 COM Dispatch 객체를 사용할 수있는 모든 언어에서 동일한 API 를 사용할 수 있습니다 . 즉, 단일 환경에 맞게 최적화되지 않은 API가 있었지만 COM 개체가 런타임에 메서드를 보급하고 확인할 수있는 추상화 계층이 많았습니다 . ArcGIS 9.3 이전을 기억한다면 Perl 및 Ruby 와 같은 많은 언어를 사용하여 지리 처리 스크립트를 작성할 수있었습니다 . 개체를 처리하기 위해 개체가 수행해야하는 추가 서류IDispatch 함수는 함수 호출에 많은 복잡성과 속도 저하를 추가합니다.
  2. 파이썬의 관용구 및 데이터 구조를 사용하여 긴밀하게 통합 된 파이썬 특정의 C ++ 라이브러리를 확인하십시오 의 아이디어 객체 와 정말 이상한 춤은 파이썬에서 비효율적 그냥 평범한했다. 목록에서 항목을 가져 오는 것은 매우 빠른 작업이며 몇 개의 CPython 함수 호출 (기본적으로 호출, 목록에 크게 최적화 됨)로 단순화됩니다 . 비교 하면 더 무거운 것입니다 : 메소드를 가져 와서 (새로운 바인딩 된 메소드 객체를 만들어야 함) 주어진 인수 ( )로 해당 메소드를 호출하십시오 . 구현 의 각 부분은 CPython API와 매우 밀접하게 통합되어 있습니다.Rowwhile cursor.Next():__getitem__row.getValue("column")__getattr____call__arcpy.da 기본 Python 데이터 구조를 사용하여 속도를 높이고 메모리 효율성을 높이기 위해 수많은 통합 된 C ++을 사용하여 빠르게 만들 수 있습니다.

또한 거의 모든 벤치 마크 ( 예 :이 슬라이드 참조 )에서 .Net 및 C ++의 arcobject가 여전히 arcpy.da대부분의 작업 보다 두 배 빠릅니다 . 파이썬 코드를 사용하는 arcpy.da것이 빠르지 만 컴파일 된 하위 언어보다 빠르지는 않습니다.

TL; DR : 빠른 Python 코드를 생성하도록 특별히 고안된 직선화되지 않은 Arcobjects / C ++ / CPython으로 구현 da되었기 때문에 더 빠릅니다 da.


4

성능 관련

  • 커서는 기본적으로 설정된 전체 필드 목록을 반복합니다 (전체 데이터베이스가 아님)

기타 성능과 직접 관련이 없지만 개선 된 기능 :

  • 기능 형상에 액세스하기 위해 토큰 (예 : SHAPE @ LENGTH, SHAPE @ XY)을 사용하는 기능
  • 데이터베이스를 안내 하는 기능 ( arpy.da.Walk 방법 사용)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.