Sposoby przyspieszenia skryptów Pythona działających jako narzędzia ArcGIS [zamknięte]

31

To dość ogólne pytanie. Zastanawiam się tylko, jakich wskazówek i trików użyli programiści GIS, aby przyspieszyć skrypty Arcpy, które importujesz do zestawu narzędzi i uruchamiasz.

Codziennie pracuję, pisząc małe skrypty, aby pomóc użytkownikom spoza GIS w moim biurze przetwarzać dane GIS. Przekonałem się, że przetwarzanie ArcGIS 10.0 jest ogólnie wolniejsze niż 9.3.1, a czasem staje się jeszcze wolniejsze po uruchomieniu skryptu python.

Wymienię konkretny przykład skryptu, którego uruchomienie zajmuje ponad 24 godziny. Jest to pętla, która tabelaryzuje obszar rastra w buforze dla każdego kształtu w buforze. Bufor ma około 7000 kształtów. Nie wierzę, że powinno to trwać tak długo. ZA

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

Zanim ktokolwiek to powie, uruchomiłem obszar tabelaryczny na całym buforze, ale powoduje błędy, jeśli działa na więcej niż jednym rekordzie. To wadliwe narzędzie, ale muszę go użyć.

W każdym razie, jeśli ktoś ma jakieś pomysły na optymalizację lub przyspieszenie tego skryptu, byłoby to bardzo mile widziane. W przeciwnym razie, czy masz jakieś sztuczki przyspieszające dla Pythona, gdy jest używane w ArcGIS?

Cody Brown
źródło

Odpowiedzi:

26

Kilka potencjalnych sugestii, które pomogą przyspieszyć proces to:

  1. Opcja Wybierz warstwę według atrybutu może znajdować się w skrypcie wyłącznie w języku Python, bez konieczności uruchamiania ArcGIS Desktop. Musisz przekonwertować referencję „buff” z referencji opartej na plikach na referencję „warstwy ArcGIS”, na podstawie której ArcGIS może przetwarzać zapytania dotyczące selekcji. Użyj arcpy.MakeFeatureLayer_management („buff”, „buff_lyr”) powyżej pętli „while”, a następnie zmień referencje poniżej pętli while, aby użyć „buff_lyr”.

  2. Przetwarzaj jak najwięcej operacji GP za pomocą obszaru roboczego in_memory, jak to możliwe ... Użyj arcpy.CopyFeatures_management (shapefile, "in_memory \ memFeatureClass"), aby przenieść źródło do pamięci. Działa to dobrze tylko wtedy, gdy masz wystarczającą ilość pamięci RAM, aby odczytać wszystkie potrzebne klasy pamięci do pamięci. Uważaj jednak, że istnieją pewne operacje GP, których nie można uruchomić przy użyciu obszaru roboczego in_memory (np .: narzędzie Projekt).

Z artykułu pomocy online ArcGIS 9.3 „ Dane pośrednie i obszar roboczy scratch ” (uwaga, ten język został usunięty z pomocy 10.0 i 10.1):

UWAGA: Tylko tabele i klasy elementów (punkty, linie, wielokąty) mogą być zapisywane w obszarze roboczym in_memory. Obszar roboczy in_memory nie obsługuje rozszerzonych elementów geobazy, takich jak podtypy, domeny, reprezentacje, topologie, sieci geometryczne i zestawy danych sieciowych. Można pisać tylko proste funkcje i tabele.

Z artykułu pomocy online ArcGIS 10.1 „ Korzystanie z przestrzeni roboczej w pamięci ”:

Przy zapisywaniu danych wyjściowych w obszarze roboczym w pamięci należy wziąć pod uwagę następujące kwestie:

  • Dane zapisane w obszarze roboczym w pamięci są tymczasowe i zostaną usunięte po zamknięciu aplikacji.
  • Tabele, klasy elementów i rastry można zapisywać w obszarze roboczym w pamięci.
  • Obszar roboczy w pamięci nie obsługuje rozszerzonych elementów geobazy, takich jak podtypy, domeny, reprezentacje, topologie, sieci geometryczne i zestawy danych sieciowych.
  • Nie można utworzyć zestawów danych ani folderów w obszarze roboczym w pamięci.
RyanDalton
źródło
1
To fantastycznie! Szukałem sposobu na użycie opcji poza ArcMap, ale jak dotąd nie powiodło się. Jeśli chodzi o ten problem, to faktycznie skróciło mój czas na wiersz do około 13 sekund z 20 sekund. Ale zrobiłem inne szybkie obejście i zrobiłem MakeFeatureLayer w pętli i spadła do 9 sekund. Zrobiłem to, tworząc element z każdego kształtu, a nie tabelując z warstwy elementów. Nadal chciałbym, jeśli to możliwe, zejść dalej, ale już teraz jest to znacznie szybszy proces!
Cody Brown
Jak wspomniano w punkcie 2, użyj CopyFeatures, aby wykonać kopię danych źródłowych in_memory, a następnie utwórz odtwarzacz Feature_layer na podstawie źródła in_memory. Podczas gdy początkowa kopia do pamięci może dodać kilka sekund z góry, może się okazać, że to przetwarzanie kopii + tabulate_areas ma szybszy całkowity czas przetwarzania niż obecny model.
RyanDalton,
Próbowałem tego również i wydaje się, że to rozwiązanie przyspieszy proces pętli, ale tak nie jest. Utworzenie warstwy cechy w pętli daje około 8-10 sekund na pętlę, podczas gdy tworzenie warstwy cechy przed pętlą daje 11 - 14 sekund na pętlę. Nie jestem pewien, dlaczego, skoro Twoje rozwiązanie wydaje się przetwarzać szybciej. Mam 8 GB pamięci RAM, więc wątpię, żeby to był problem.
Cody Brown,
Również skopiowanie funkcji do in_memory przed pętlą, a następnie nadal tworzenie warstwy funkcji w pętli, powoduje nieco większą wydajność. Pozostaje prawie 8 sekund na wiersz dla każdej pętli. Co skróci całkowity czas procesu z 26 godzin do 22.
Cody Brown
Po dodaniu pomysłów mój skrypt znacznie się poprawił. Wielkie dzięki za twoją i pomoc wszystkich!
Cody Brown
28

Ogólne techniki optymalizacji Pythona mogą zaoszczędzić znaczną ilość czasu.

Jedną z naprawdę dobrych technik uzyskiwania informacji o tym, gdzie są błędy w skrypcie, jest użycie wbudowanego modułu cProfile:

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

Testowanie przy użyciu niewielkiej próbki danych pozwoli ci określić, które wywołania funkcji zajmują najwięcej czasu.

Ogólne wskazówki dotyczące szybszego kodu python:

  • Zrozumienie listy jest na ogół szybsze niż zapętlanie
  • Generatory wytwarzają jeden element na raz, zamiast tworzyć jednocześnie całą listę
  • Użyj xrange zamiast zakresu w python 2 (niepotrzebne w 3)
  • Zestawy mogą tworzyć listy preform, jeśli chodzi o ustalenie, czy element jest obecny w zestawie, ale są ogólnie wolniejsze niż listy, jeśli chodzi o iterację ich zawartości Źródło
  • Wywołania funkcji mogą być kosztowne dla wydajności Źródło
  • Więcej wskazówek i szczegółów sprawdź tutaj Wskazówki dotyczące wydajności Python i tutaj 10 Wskazówki i problemy dotyczące optymalizacji Python

Jeśli chodzi o twój skrypt, nie mogę komentować aspektów ArcPy, ponieważ nie mam Arc zainstalowanej na tym komputerze, ale możesz spróbować użyć pętli for zamiast pętli while, aby sprawdzić, czy coś to poprawi. Również x = x + 1 można zapisać jako 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
James Milner
źródło
1
Użyłem dwóch linków, które pozostawiłeś w ostatniej kuli i byłem w stanie naprawdę pomóc mojemu skryptowi za pomocą kilku szybkich poprawek!
Cody Brown,
Gdybym mógł udzielić dwóch poprawnych odpowiedzi, zrobiłbym to. Podczas gdy twoja odpowiedź naprawdę zawierała wiele pomysłów na przyspieszenie Pythona, @RyanDalton zaproponował te, które miały największy wpływ. Wielkie dzięki!
Cody Brown
13

Upewnij się, że piszesz na wewnętrzny dysk komputera. Dotarcie do sieci, gdy nie jest to konieczne, może naprawdę spowolnić przetwarzanie. Kopiowanie danych może być nawet szybsze jako pierwszy krok w procesie, aby kolejne zapisy do odczytu były jak najszybsze

Uruchomienie skryptu całkowicie poza ArcMap może być znacznie szybsze. Jeśli mapa nie jest wymagana podczas przetwarzania, nie używaj ArcMap.

mhoran_psprep
źródło
Odkryłem, że uruchomienie skryptu w modelu z ArcCatalog (samo w Calculate Valueoknie dialogowym) będzie przetwarzane szybciej niż uruchomienie tego samego skryptu z okna ArcPy w ArcMap. To jednak czysto anegdotyczne spostrzeżenie.
Cindy Jayakumar,
1
Myślę, że potrzebuję mapy, aby Tabulate działał poprawnie, ale zamierzam spróbować. Jeśli działa poza ArcMap, założę się, że przyspieszyłoby. Poza tym już uciekam z dysku lokalnego, co już podwoiło prędkość skryptu.
Cody Brown,
Niestety Select nie działa poza ArcMap i jest to konieczne, ponieważ muszę tworzyć tabulacje kształt po kształcie.
Cody Brown
3
@ CodyBrown - Mylisz się co do tego, że Select nie działa poza sesją ArcMap. Zobacz moją odpowiedź na temat korzystania z narzędzia MakeFeatureLayer.
RyanDalton,
Ryan ma rację. Gdy narzędzie wyboru jest używane samodzielnie, tworzy widok tabeli danych przestrzennych lub danych tabeli. Używając go w ModelBuilde lub w skrypcie, musisz utworzyć widok, aw twoim przypadku, utwórz go za pomocą narzędzia MakeFeatureLayer.
dchaboya,
6

To może nie odpowiedzieć na twoje pytanie dotyczące uruchamiania narzędzi ArcPy w ArcMap, ale kiedy muszę wykonać mięsiste przetwarzanie za pomocą narzędzi do geo-przetwarzania i Pythona, zwykle uruchamiam je poza systemem GIS za pomocą PyEcriptera IDE . Odkryłem, że działa szybciej. Użyłem również RAMDISK dla małych tymczasowych zbiorów danych wyjściowych (trochę jak obszar roboczy in_memory )

Cóż, to moje najlepsze wskazówki! :)

Hornbydd
źródło
2
Aby nieco otępić tę odpowiedź, podczas uruchamiania skryptów z IDE Pythona wielu wstrzykuje funkcję śledzenia wstecznego, aby pomóc w oglądaniu zmiennych i innych pomocnych metodach debugowania. Ta funkcja może znacznie spowolnić skrypty, jeśli robi zbyt wiele, gdy nazywa się CAŁY CZAS, a czasami jest to instalowane domyślnie bez interwencji użytkownika. Zaobserwowałem szczególny przypadek patologiczny, w którym skrypt Pythona działający w ArcMap działał w 4 minuty, podczas gdy ten sam skrypt z Wing IDE trwał 3 godziny. Gdy tylko został uruchomiony z Python.exe bez Wing, wrócił do ~ 2-3 minutowego terytorium wykonawczego.
Jason Scheirer,
1
Miałem problemy z dostrajaniem skryptów na ArMap, czasami nie mogę tego całkowicie, dopóki nie zwróciłem się do Pyscripter, może to skrócić czas wykonania w porównaniu do Arcmap, bez użycia jakiejkolwiek wskazówki optymalizacyjnej.
geogeek
@JasonScheirer, czy znalazłeś usprawnienie w usłudze Wing, aby to wyłączyć? Jestem pewien, że jest jeden.
Curtis Price
5

Spróbuj skomentować arcpy.SetProgressorLabel i zobacz, jak bardzo przyspieszysz. Przekonałem się, że każde wyjście ekranu, wracając do oszałamiającego DOS, drastycznie spowalnia czas przetwarzania. Jeśli naprawdę potrzebujesz zobaczyć ten wynik, spróbuj wyświetlić go w każdej pętli N-tej.

użytkownik30749
źródło
4

Upewnij się, że usuwasz wszystkie import xxxxnieużywane linie.

(tzn. jeśli jeszcze nie korzystasz z żadnych funkcji matematycznych, import Mathładowanie skryptu zajmie trochę czasu)

Chociaż nie będzie to miało wielkiego wpływu na uruchamiane pojedyncze skrypty (takie jak twoje), wpłynie to na wszystkie skrypty, które są uruchamiane często i powtarzalnie.

nagytech
źródło
7
Wątpię, czy jakikolwiek standardowy moduł Python zajmuje więcej niż jedną tysięczną czasu inicjalizacji modułu Arcpy.
blah238,
1
@ blah238 import Mathbył prawdopodobnie złym przykładem. Jednak załadowanie niektórych większych bibliotek ArcPy zajmuje dużo czasu.
nagytech,
1
to wciąż goli tylko sekundy (najwyżej!), a nie godziny
Mike T
1
@MikeToews W przypadku skryptów, które działają często i powtarzalnie, kilka sekund sumuje się w ciągu kilku dni / tygodni itp. Chociaż ta dawka nie rozwiązuje głównego problemu PO, poprosił o ogólne wskazówki.
nagytech,