Làm thế nào là hiệu suất con trỏ truy cập dữ liệu được tăng cường so với các phiên bản trước?


18

Mô-đun truy cập dữ liệu được giới thiệu với ArcGIS phiên bản 10.1. ESRI mô tả mô-đun truy cập dữ liệu như sau ( nguồn ):

Mô-đun truy cập dữ liệu, arcpy.da, là mô-đun Python để làm việc với dữ liệu. Nó cho phép kiểm soát phiên chỉnh sửa, thao tác chỉnh sửa, hỗ trợ con trỏ được cải thiện (bao gồm hiệu suất nhanh hơn), các chức năng để chuyển đổi bảng và các lớp tính năng sang và từ mảng NumPy và hỗ trợ cho quy trình làm việc phiên bản, bản sao, tên miền và kiểu con.

Tuy nhiên, có rất ít thông tin liên quan đến lý do tại sao hiệu suất con trỏ được cải thiện so với thế hệ con trỏ trước đó.

Hình đính kèm cho thấy kết quả của một bài kiểm tra điểm chuẩn trên daphương thức UpdateCoder mới so với phương thức UpdateCoder cũ. Về cơ bản, tập lệnh thực hiện quy trình công việc sau:

  1. Tạo điểm ngẫu nhiên (10, 100, 1000, 10000, 100000)
  2. Lấy mẫu ngẫu nhiên từ một phân phối bình thường và thêm giá trị vào một cột mới trong bảng thuộc tính điểm ngẫu nhiên bằng một con trỏ
  3. Chạy 5 lần lặp của mỗi kịch bản điểm ngẫu nhiên cho cả phương thức UpdateCoder mới và cũ và ghi giá trị trung bình vào danh sách
  4. Vẽ kết quả

Điều gì đang xảy ra đằng sau hậu trường với dacon trỏ cập nhật để cải thiện hiệu suất con trỏ đến mức độ được hiển thị trong hình?


nhập mô tả hình ảnh ở đây


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()

Câu trả lời:


25

Một trong những nhà phát triển arcpy.daở đây. Chúng tôi có hiệu suất như vậy bởi vì hiệu suất là mối quan tâm chính của chúng tôi : sự kìm kẹp chính với các con trỏ cũ là chúng chậm, không phải là chúng thiếu bất kỳ chức năng cụ thể nào. Mã này sử dụng cùng các ArcObject bên dưới có sẵn trong ArcGIS kể từ 8.x (ví dụ, triển khai CPython của con trỏ tìm kiếm, trông rất giống các mẫu mã như thế này trong triển khai của nó , ngoại trừ, trong C ++ thay vì C #).

Do đó, hai điều chính chúng tôi đã làm để tăng tốc là:

  1. Loại bỏ các lớp trừu tượng: việc triển khai con trỏ Python ban đầu dựa trên đối tượng GPDispatch dựa trên Dispatch / COM cũ , cho phép một người sử dụng cùng một API trong bất kỳ ngôn ngữ nào có thể sử dụng các đối tượng COM Dispatch . Điều này có nghĩa là bạn đã có một API không được tối ưu hóa đặc biệt cho bất kỳ môi trường nào, nhưng điều đó cũng có nghĩa là có rất nhiều lớp trừu tượng cho các đối tượng COM để quảng cáo và giải quyết các phương thức trong thời gian chạy, chẳng hạn. Nếu bạn còn nhớ trước ArcGIS 9.3, có thể viết các tập lệnh xử lý địa lý bằng cách sử dụng cùng một giao diện lộn xộn đó với nhiều ngôn ngữ, thậm chí cả Perl và Ruby . Các giấy tờ bổ sung mà một đối tượng cần phải làm để xử lýIDispatch công cụ thêm rất nhiều phức tạp và làm chậm các cuộc gọi chức năng.
  2. Tạo một thư viện C ++ cụ thể, tích hợp Python bằng cách sử dụng các thành ngữ và cấu trúc dữ liệu của Pythonic: ý tưởng về một Rowđối tượngwhile cursor.Next():điệu nhảy thực sự kỳ lạ chỉ là không hiệu quả trong Python. Tìm nạp một mục từ danh sách là một thao tác rất nhanh và đơn giản hóa chỉ một vài lệnh gọi hàm CPython (về cơ bản là một __getitem__cuộc gọi, được tối ưu hóa rất nhiều trong danh sách). Làm row.getValue("column")bằng cách so sánh thì nặng hơn: nó thực hiện __getattr__để tìm nạp phương thức (trên đó nó cần tạo một đối tượng phương thức ràng buộc mới), sau đó gọi phương thức đó với các đối số đã cho ( __call__). Mỗi phần của việc arcpy.datriển khai được tích hợp rất chặt chẽ với API CPython với rất nhiều C ++ được điều chỉnh bằng tay để làm cho nó nhanh, sử dụng các cấu trúc dữ liệu Python nguyên gốc (và tích hợp gọn gàng, cho tốc độ và hiệu quả bộ nhớ cao hơn nữa).

Bạn cũng sẽ nhận thấy rằng trong gần như bất kỳ điểm chuẩn nào ( ví dụ như xem các slide này ), các arcobject trong .Net và C ++ vẫn nhanh hơn gấp đôi so với arcpy.datrong hầu hết các tác vụ. Mã Python sử dụng arcpy.danhanh hơn, nhưng vẫn không nhanh hơn ngôn ngữ được biên dịch, cấp thấp hơn.

TL; DR : danhanh hơn vì dađược triển khai trong Arcobjects / C ++ / CPython thẳng, không được lọc được thiết kế đặc biệt để tạo ra mã Python nhanh.


4

Hiệu suất liên quan

  • Con trỏ chỉ lặp qua danh sách các trường theo mặc định (không phải toàn bộ cơ sở dữ liệu)

Khác không liên quan trực tiếp đến hiệu suất, nhưng cải tiến tốt đẹp:

  • Khả năng sử dụng mã thông báo (ví dụ: SHAPE @ LENGTH, SHAPE @ XY) để truy cập hình học tính năng
  • Khả năng đi qua cơ sở dữ liệu (sử dụng phương pháp arcpy.da.Walk )
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.