Wydajność ArcGISScripting i dużych zestawów danych przestrzennych

38

Obecnie piszę skrypt w języku Python za pomocą modułu arcgisscripting do przetwarzania stosunkowo dużego zestawu danych (łącznie około 10 000 rekordów) znormalizowanego w niewielkiej liczbie tabel, w sumie 8. Proces ten polega na utworzeniu elementu opartego na krotkach współrzędnych (x, y) i utworzeniu wykresu (węzły i linie) przy użyciu relacji z pozostałych 7 tabel jako wskazówek. Ostatecznym wynikiem jest osobna geobaza (pgdb / fgdb) z zestawami danych przestrzennych węzłów i krawędzi, które wizualnie reprezentują relacje.

Moja pierwsza próba polegała na użyciu zapytań o nowe tabele geobazy i zestawy rekordów SearchCursor w celu zapełnienia tabel linków (InsertCursor) dla występujących relacji wiele do wielu. Działało to bardzo dobrze, z wyjątkiem 15-20 minutowego czasu przetwarzania.

Używając modułu cProfiler w Pythonie, było oczywiste, że „przerzucenie” osobistej geobazy podczas wykonywania zapytań w celu zapełnienia tabel linków żądaniami kursorów (Wyszukaj i Wstaw kursory) spowodowało przerażającą wydajność.

Przy odrobinie refaktoryzacji udało mi się uzyskać czas przetwarzania poniżej 2,5 minuty. Kompromis polegał na częściowej budowie schematu geobazy w kodzie i ograniczeniu żądań kursorów arcgisscripting do InsertCursors po zestawieniu wszystkich relacji.

Moje pytanie dotyczy wydajności;

  • Jakie techniki zastosowali ludzie, aby utrzymać rozsądne czasy obliczeń podczas pracy z dużym zestawem danych?
  • Czy są jakieś metody zalecane przez ESRI, których nie zauważyłem przy poszukiwaniu optymalizacji?

    Rozumiem narzut związany z tworzeniem kursora tworzenia skryptów, zwłaszcza jeśli pochodzi on z osobistej geobazy, choć po długim poszukiwaniu odpowiedzi związanych z wydajnością z tej witryny i Google mam wrażenie, że wydajność nie jest najważniejsza w przedsięwzięciach ludzi .

  • Czy jako użytkownik produktów ESRI oczekujesz i akceptujesz te opóźnienia w wydajności?

AKTUALIZACJA

Po kilku pracach z tym produktem zgromadziłem listę technik optymalizacji, które podjęły proces konwersji informacji przestrzennej z odpowiedniego formatu na geobazę. Zostało to opracowane dla osobistej i geobazy danych. Ciekawostki:

  1. Czytaj dane i racjonalizuj je w pamięci. To skróci Twój czas o połowę.

  2. Twórz klasy obiektów i tabele w pamięci. Użyj klucza funkcji zestawu danych „in_memory”, aby użyć pamięci jako dysku RAM, wykonać tam swoje funkcje, a następnie zapisać na dysk

  3. Aby zapisać na dysk, użyj klasy CopyFeature dla klas elementów i CopyRow dla tabel.

Te 3 rzeczy wymagały skryptu, który przekształcił ponad 100 000 obiektów w geobazę z 30 minut do 30 - 40 sekund, w tym klasy relacji. Nie należy ich używać lekko, większość powyższych metod zużywa dużo pamięci, co może powodować problemy, jeśli nie zwracasz uwagi.

OptimizePrime
źródło
1
Czy próbowałeś użyć innego formatu pamięci? Jak działa geobaza danych pliku?
Derek Swingley,
Geobazy danych plikowych działają nieco gorzej niż osobiste geobazy danych. Wczoraj spędziłem konfigurowanie i dostrajanie instancji ArcSDE w celu przetestowania wydajności w formacie korporacyjnym. Będę cię informować o moich odkryciach
OptimizePrime
2
To ci teraz nie pomaga, ale w 10.1 wydajność kursora w Pythonie została poprawiona o ogromny czynnik (coś w zakresie wielkości rzędu średnich przypadków) dzięki nowemu modułowi dostępu do danych.
Jason Scheirer
In_memory korzysta z InMemoryWorkspace edndoc.esri.com/arcobjects/9.2/ComponentHelp/esriDataSourcesGDB/..., który po dowolnej liczbie wierszy zrzuca wszystko do ScratchWorkspaceFactory (tj. FileGDB) i wykonuje całą pracę
Ragi Yaser Burhum

Odpowiedzi:

56

Chociaż na to pytanie już udzielono odpowiedzi, pomyślałem, że mogę wrzucić dwadzieścia centów.

ZASTRZEŻENIE : Pracowałem dla ESRI w zespole GeoDatabase przez kilka lat i byłem odpowiedzialny za utrzymanie różnych części kodu GeoDatabase (wersjonowanie, kursory, edycja sesji, historia, klasy relacji itp.).

Myślę, że największym źródłem problemów z wydajnością kodu ESRI nie jest zrozumienie implikacji używania różnych obiektów, w szczególności „małych” szczegółów różnych abstrakcji GeoDatabase! Bardzo często rozmowa przełącza się na język używany jako sprawca problemów z wydajnością. W niektórych przypadkach może tak być. Ale nie cały czas. Zacznijmy od dyskusji na temat języka i cofnijmy się.

1.- Wybrany język programowania ma znaczenie tylko wtedy, gdy robisz coś skomplikowanego, w ciasnej pętli. W większości przypadków tak nie jest.

Duży słoń w pokoju polega na tym, że u podstaw całego kodu ESRI znajdują się ArcObjects - a ArcObjects jest napisane w C ++ przy użyciu COM . Komunikowanie się z tym kodem kosztuje. Odnosi się to do C #, VB.NET, python lub czegokolwiek innego używasz.

Płacisz cenę przy inicjalizacji tego kodu. Może to być nieistotny koszt, jeśli zrobisz to tylko raz.

Następnie płacisz cenę za każde kolejne interakcje z ArcObjects.

Osobiście mam tendencję do pisania kodu dla moich klientów w języku C #, ponieważ jest to łatwe i wystarczająco szybkie. Jednak za każdym razem, gdy chcę przenosić dane lub przetwarzać duże ilości danych, które są już zaimplementowane w Geoprocessing , po prostu inicjuję podsystem skryptów i przekazuję moje parametry. Czemu?

  • Jest już zaimplementowany. Po co więc wymyślać koło?
  • To może być rzeczywiście szybsze . „Szybsze niż pisanie w C #?” Tak! Jeśli zaimplementuję, powiedzmy, ładowanie danych ręcznie, oznacza to, że płacę cenę przełączania kontekstu .NET w ścisłej pętli. Każde GetValue, Insert, ShapeCopy ma swój koszt. Jeśli wykonam jedno wywołanie w GP, cały proces ładowania danych nastąpi w rzeczywistej implementacji GP - w C ++ w środowisku COM. Nie płacę ceny za zmianę kontekstu, ponieważ jej nie ma - i dlatego jest szybsza.

Ach tak, więc rozwiązaniem jest użycie wielu funkcji geoprzetwarzania. Właściwie musisz być ostrożny.

2. GP to czarna skrzynka, która kopiuje dane (potencjalnie niepotrzebnie)

Jest to miecz obosieczny. Jest to czarna skrzynka, która wykonuje trochę magii wewnętrznie i wypluwa wyniki - ale te wyniki są bardzo często powielane. 100 000 wierszy można łatwo przekonwertować na 1 000 000 wierszy na dysku po uruchomieniu danych przez 9 różnych funkcji. Używanie tylko funkcji GP jest jak tworzenie liniowego modelu GP i dobrze ...

3. Łączenie zbyt wielu funkcji GP dla dużych zestawów danych jest wysoce nieefektywne. Model GP jest (potencjalnie) równoważny do wykonania zapytania w naprawdę naprawdę głupi sposób

Nie zrozum mnie źle. Uwielbiam modele GP - oszczędza mi to ciągłego pisania kodu. Ale mam również świadomość, że nie jest to najbardziej wydajny sposób przetwarzania dużych zbiorów danych.

Czy wszyscy słyszeliście o narzędziu do planowania zapytań ? Jego zadaniem jest spojrzenie na instrukcję SQL, którą chcesz wykonać, wygenerowanie planu wykonania w postaci ukierunkowanego wykresu, który wygląda jak model GP , spojrzenie na statystyki przechowywane w bazie danych i wybranie najbardziej optymalna kolejność ich wykonania . GP po prostu wykonuje je w kolejności, w jakiej je umieściłeś, ponieważ nie ma statystyk, aby zrobić cokolwiek bardziej inteligentnie - jesteś planistą zapytań . I zgadnij co? Kolejność wykonywania rzeczy jest bardzo zależna od zestawu danych. Kolejność wykonywania rzeczy może mieć znaczenie między dniami i sekundami i to od Ciebie zależy.

„Świetnie”, mówisz, nie będę sam pisać scenariuszy i będę uważał na to, jak piszę. Ale czy rozumiesz abstrakcje GeoDatabase?

4. Niezrozumienie abstrakcji GeoDatabase może cię łatwo ugryźć

Zamiast wskazywać każdą rzecz, która może sprawić ci problem, pozwól mi tylko wskazać kilka typowych błędów, które widzę cały czas, i kilka rekomendacji.

  • Zrozumienie różnicy między kursorem True / False for Recycling . Ta niewielka mała flaga ustawiona na true może przyspieszyć rzędy czasu działania.
  • Umieść tabelę w LoadOnlyMode dla ładowań danych. Po co aktualizować indeks na każdej wkładce?
  • Zrozum, że chociaż IWorkspaceEdit :: StartEditing wygląda tak samo we wszystkich obszarach roboczych, są one bardzo różnymi bestiami w każdym źródle danych. W Enterprise GDB możesz mieć wersję lub obsługę transakcji. W plikach kształtu będzie musiał zostać zaimplementowany w zupełnie inny sposób. Jak wdrożyłbyś Cofnij / Ponów? Czy w ogóle musisz go włączyć (tak, może to zmienić użycie pamięci).
  • Różnica między operacjami wsadowymi lub operacjami jednorzędowymi. Sprawa w punkcie GetRow vs GetRows - jest to różnica pomiędzy robi kwerendę, aby uzyskać jeden wiersz lub wykonując jedną kwerendę, aby pobrać wiele wierszy. Ścisła pętla z wezwaniem do GetRow oznacza straszną wydajność i jest winowajcą nr 1 problemów z wydajnością
  • Użyj UpdateSearchedRows
  • Zrozum różnicę między CreateRow i CreateRowBuffer . Ogromna różnica w czasie wykonywania wstawiania.
  • Zrozum, że IRow :: Store i IFeature :: Store wyzwalają bardzo ciężkie operacje polimorficzne . Jest to prawdopodobnie powód nr 2 sprawcy naprawdę niskiej wydajności. Nie tylko zapisuje wiersz, jest to metoda, która upewnia się, że twoja sieć geometryczna jest w porządku, że ArcMap Editor zostaje powiadomiony o zmianie wiersza, który powiadamia wszystkie klasy relacji, które mają cokolwiek wspólnego z tym wierszem, aby sprawdzić poprawność upewnij się, że liczność jest poprawna itp. Nie powinieneś wstawiać przy tym nowych wierszy, powinieneś używać InsertCursor !
  • Czy chcesz (potrzebujesz) wykonać te wstawki w sesji edycji? To robi ogromną różnicę, jeśli tak, czy nie. Niektóre operacje tego wymagają (i spowalniają pracę), ale jeśli nie potrzebujesz, pomiń funkcje cofania / ponawiania.
  • Kursory to drogie zasoby. Kiedy już będziesz miał do tego rękojeść, masz gwarancję, że będziesz miał spójność i izolację, a to będzie kosztować.
  • Buforuj inne zasoby, takie jak połączenia z bazą danych (nie twórz i nie niszcz odwołania do obszaru roboczego) i uchwyty tabel (za każdym razem, gdy je otwierasz lub zamykasz - trzeba odczytać kilka tabel metadanych).
  • Umieszczenie FeatureClasses wewnątrz lub na zewnątrz FeatureDataset robi ogromną różnicę w wydajności. Jest to nie oznaczało, jako element porządkujący!

5. I na koniec ...

Zrozumienie różnicy między operacjami związanymi z operacjami we / wy i procesorami

Szczerze, myślałem o rozszerzeniu każdego z tych elementów i być może zrobieniu serii wpisów na blogu, które obejmują każdy z tych tematów, ale lista zaległości mojego kalendarza właśnie uderzyła mnie w twarz i zaczęła na mnie krzyczeć.

Moje dwa centy.

Ragi Yaser Burhum
źródło
5
dzięki. Powinienem był pracować zamiast pisać ten post haha
Ragi Yaser Burhum
3
+1 Bardzo dziękuję za wkład, panie Burhum. To jest rodzaj odpowiedzi, którą chciałem otrzymać. Gdybym mógł zagłosować dwa razy, mógłbym !! Użytkownicy ArcGISScripting (python) powinni wziąć z tej odpowiedzi, chociaż linki odzwierciedlają koncepcje ArcObjects i .Net, leżące u ich podstaw obiekty COM są takie same, zrozumienie tych obiektów pomoże lepiej zaplanować kod w dowolnym języku. Wiele świetnych informacji tutaj !!
OptimizePrime
1
@OptimizePrime To świetne podsumowanie. I masz rację - nie możesz zignorować implikacji ArcObjects, jeśli chcesz wycisnąć wydajność z produktów ESRI
Ragi Yaser Burhum
1
dzięki, zamieniłem store () na wstawianie kursorów i zaoszczędziłem dużo czasu w moich aplikacjach!
superrache
5

Ogólnie rzecz biorąc, do obliczeń wydajności staram się unikać używania rzeczy związanych z ESRI. Na przykład proponuję wykonanie procesu etapami, pierwszy krok odczytuje dane do normalnych obiektów Pythona, wykonuje obliczenia, a następnie ostatni krok konwertuje do końcowego formatu przestrzennego ESRI. W przypadku około 10 000 rekordów prawdopodobnie można by uniknąć przechowywania wszystkiego w pamięci do przetwarzania, co dałoby wyraźny wzrost wydajności.

Anthony -GISCOE-
źródło
Dziękuję za odpowiedź. To dobra sugestia. Zacząłem refaktoryzować kod, aby wykonać wymagane procedury przed użyciem arcgisscripting. Po pracy z oprogramowaniem od czasów ArcInfo frustruje mnie wzrost wydajności procesora i możliwości sprzętowych, wydajność ArcGIS Map / Info / Editor XX jest w stagnacji. Może wprowadzenie GPU może poprawić sytuację. Chociaż dobry refaktor bazy kodu ESRI może również pomóc
OptimizePrime
1

W zależności od posiadanego sprzętu możesz również rozważyć opcję wyświetloną w przykładzie geokodera ESRI; daje ci strukturę do rozbicia dużego zbioru danych i uruchomienia wielu instancji Pythona, aby uzyskać prawie wielowątkowe podejście. Zauważyłem, że wydajność geokodowania wzrosła z 180 000 na godzinę w pojedynczej instancji Pythona do ponad miliona dzięki rozkręceniu 8 równoległych procesów na moim komputerze.

Widziałem, że odejście jak najwięcej i utrzymanie pracy danych w bazie danych, praca funkcjonalna w moich tabelach i samo użycie jawnego GIS w dziedzinie ESRI daje znaczny wzrost wydajności.

DEWright
źródło
To są świetne pomysły. Mam możliwość wątkowania niektórych procesów w tym skrypcie, ale okazuje się, że moje szyjki butelki inicjują biblioteki COM i I / O Geodatabase. Jeśli chodzi o wejścia / wyjścia, zmniejszyłem potrzebę jednego zapisu. Jeśli spędzę więcej czasu na optymalizacji, mój szef będzie się dobrze czuł;) Więc zostawiam wątki jako ostatnie ograniczenie wydajności, jeśli poprosi o więcej. W tej chwili przetwarzam 60 000 funkcji na minutę.
OptimizePrime
0

Te inne posty na forum mogą Cię zainteresować, ponieważ znajdują się w kontekście optymalizacji, ale dla danych rastrowych i ogólnie:

Kompilujesz skrypty Pythona korzystające z narzędzi geoprzetwarzania ArcGIS?

Czas przetwarzania przy użyciu narzędzi ArcGIS Hydrology Toolbox w samodzielnym skrypcie Python vs ArcCatalog?

ustawienie gp.scratchworkspace zrobiło dla mnie dużą różnicę w kodzie Pythona, który napisałem do robienia zlewów.

Czy możesz zamieścić kilka przykładów kodu, które pokazują liczby 1 i 2 w aktualizacji w oryginalnym pytaniu? Chciałbym zobaczyć mechanikę tego (choć zakładam, że masz do czynienia z danymi klasy obiektów tylko tutaj)

dzięki, Tom

turkishgold
źródło