Maksymalizacja wykorzystania procesora

9

Mój skrypt przecina linie z wielokątami. To długi proces, ponieważ istnieje ponad 3000 linii i ponad 500000 wielokątów. Wykonałem z PyScripter:

# Import
import arcpy
import time

# Set envvironment
arcpy.env.workspace = r"E:\DensityMaps\DensityMapsTest1.gdb"
arcpy.env.overwriteOutput = True

# Set timer
from datetime import datetime
startTime = datetime.now()

# Set local variables
inFeatures = [r"E:\DensityMaps\DensityMapsTest.gdb\Grid1km_Clip", "JanuaryLines2"]
outFeatures = "JanuaryLinesIntersect"
outType = "LINE"

# Make lines
arcpy.Intersect_analysis(inFeatures, outFeatures, "", "", outType)

#Print end time
print "Finished "+str(datetime.now() - startTime)


Moje pytanie brzmi: czy istnieje sposób, aby procesor działał na 100%? Cały czas działa przy 25%. Myślę, że skrypt działałby szybciej, gdyby procesor był w 100%. Błędne zgadywanie?
Moja maszyna to:

  • Windows Server 2012 R2 Standard
  • Procesor: Intel Xeon CPU E5-2630 0 @ 2,30 GHz 2,29 GHz
  • Zainstalowana pamięć: 31,6 GB
  • Typ systemu: 64-bitowy system operacyjny, procesor x64


wprowadź opis zdjęcia tutaj

Manuel Frias
źródło
Zdecydowanie zaleciłbym wybór wielowątkowości. To nie jest łatwe do skonfigurowania, ale z nadwyżką zrekompensuje wysiłki.
alok jha
1
Jaki indeks przestrzenny zastosowałeś do swoich wielokątów?
Kirk Kuykendall
1
Czy próbowałeś również tej samej operacji z ArcGIS Pro? Jest 64-bitowy i obsługuje wielowątkowy. Byłbym zaskoczony, jeśli jest wystarczająco inteligentny, aby podzielić przecięcie na wiele wątków, ale warto spróbować.
Kirk Kuykendall
Klasa elementów wielokąta ma indeks przestrzenny o nazwie FDO_Shape. Nie myślałem o tym. Czy powinienem stworzyć kolejny? Czy to nie wystarczy?
Manuel Frias,
1
Ponieważ masz dużo pamięci RAM ... czy próbowałeś skopiować wielokąty do klasy obiektów w pamięci, a następnie przeciąć z tym linie? A jeśli trzymasz go na dysku, czy próbowałeś go kompaktować? Podobno kompaktowanie poprawia operacje we / wy.
Kirk Kuykendall

Odpowiedzi:

13

Niech zgadnę: Twój procesor ma 4 rdzenie, więc 25% użycie procesora to 100% użycie jednego rdzenia i 3 wolnych rdzeni.

Jedynym rozwiązaniem jest uczynienie kodu wielowątkowym, ale nie jest to proste zadanie.

MTilsted
źródło
4
Wspomniany procesor wykorzystuje 6 rdzeni i 12 wątków.
Kersten
5
Cześć, nie mogę przegłosować, ale chciałbym! Python ma GIL niestety, więc nie możesz w ogóle wielowątkowości (najlepiej, co możesz zrobić, to odblokować GIL, gdy wątek blokuje się
Alec Teal
2
@AlecTeal na pewno możesz, na przykład za pomocą Jython lub multiprocessingmodułu.
prawej
@elyse: „O tak, możesz całkowicie to zrobić w Pythonie, jeśli przez Python masz na myśli Jython”, to się nie liczy. Musiałbym przyjrzeć się przetwarzaniu wieloprocesowemu, czy import mógłby ponownie wdrożyć to, co czyni Python Python?
Alec Teal
@AlecTeal Odradza procesy (które są jednym ze sposobów wykonywania równoległości). Zobacz dokumentację multiprocessingmodułu.
prawej
13

Nie jestem pewien, czy jest to zadanie związane z procesorem. Myślałem, że będzie to operacja związana z operacjami we / wy, więc chciałbym użyć najszybszego dysku, do którego miałem dostęp.

Jeśli E: to dysk sieciowy, wyeliminowanie tego byłoby pierwszym krokiem. Jeśli nie jest to dysk o wysokiej wydajności (szukanie <7 ms), to byłby drugi. Można uzyskać pewną korzyść z kopiowania warstwy wielokąta do in_memoryobszaru roboczego, ale korzyść może zależeć od wielkości klasy elementów wielokąta i od tego, czy używasz 64-bitowego przetwarzania w tle.

Optymalizacja przepustowości we / wy jest często kluczem do wydajności GIS, dlatego zalecałbym, abyś mniej zwracał uwagę na miernik procesora, a więcej na mierniki sieciowe i dyskowe.

Vince
źródło
4

Miałem podobne problemy z wydajnością dotyczące skryptów Arcpy, głównym wąskim gardłem nie jest procesor, ale dysk twardy, jeśli używasz danych z sieci, co jest najgorszym scenariuszem, spróbuj przenieść dane na dysk SSD, a następnie uruchom skrypt z wiersza polecenia nie z pyscriptera, pyscripter jest nieco wolniejszy, może dlatego, że zawiera pewne elementy do debugowania, jeśli nie będziesz zadowolony, pomyśl o paralelizacji skryptu, ponieważ każdy wątek python zajmuje jeden rdzeń procesora, twój procesor ma 6 rdzeni, więc możesz uruchomić 6 skryptów jednocześnie.

geogeek
źródło
3

Ponieważ używasz Pythona i jak zasugerowano powyżej, rozważ użycie przetwarzania wieloprocesowego, jeśli problem można uruchomić równolegle.

Napisałem mały artykuł na stronie geonet o konwertowaniu skryptu python na narzędzie skryptu python, które może być użyte w programie budującym modele. W dokumencie wymieniono kod i opisano niektóre pułapki związane z uruchomieniem go jako narzędzia skryptowego. To tylko jedno miejsce, aby zacząć szukać:

https://geonet.esri.com/docs/DOC-3824

Hornbydd
źródło
To wydaje się być właściwą drogą! Twój skrypt działa dobrze, ale nie wiem, jak go zmodyfikować, aby działał z moim skryptem. Lepiej, myślałem o zrobieniu skrzyżowania tabelarycznego z wielokątami i liniami. Dowolny pomysł?
Manuel Frias,
3

Jak powiedziano wcześniej, powinieneś używać przetwarzania wielowątkowego lub wątków . Ale tu pojawia się zastrzeżenie: problem musi być podzielny! Zajrzyj więc na https://en.wikipedia.org/wiki/Divide_and_conquer_algorithms .

Jeśli twój problem jest podzielny, postępuj następująco:

  • Utwórz kolejkę, w której przechowujesz dane wejściowe dla procesów / wątku
  • Utwórz kolejkę, w której przechowywane są wyniki
  • Utwórz funkcję lub klasę, która może być używana jako proces / wątek, który rozwiązuje nasz problem

Ale, jak powiedział geogeek, może to nie być problem z ograniczeniem procesora, ale IO. Jeśli masz wystarczającą ilość pamięci RAM, możesz wstępnie załadować wszystkie dane, a następnie przetworzyć je, co ma tę zaletę, że dane można odczytać za jednym razem, dlatego nie zawsze przerywa proces obliczania.

Benzoes
źródło
3

Postanowiłem przetestować go przy użyciu 21513 linii i 498596 wielokątów. Testowałem podejście wieloprocesorowe (12 procesorów na moim komputerze), używając tego skryptu:

import arcpy,os
import multiprocessing
import time
t0 = time.time()
arcpy.env.overwriteOutput = True
nProcessors=4
folder=r'd:\scratch'

def function(inputs):
        nGroup=inputs[0]
        pGons=inputs[1]
        lines=inputs[2]
        outFeatures = '%s%s%s_%i.shp' %(folder,os.sep,'inters',nGroup)
        fids= tuple([i for i in range(nGroup,500000,nProcessors-1)])
        lyr='layer%s'%nGroup
        query='"FID" in %s' %str(fids)
        arcpy.MakeFeatureLayer_management(pGons,lyr,query)
        arcpy.Intersect_analysis([lines,lyr], outFeatures)
        return outFeatures
if __name__ == "__main__":
        inPgons='%s%s%s' %(folder,os.sep,'parcels.shp')
        inLines='%s%s%s' %(folder,os.sep,'roads.shp')
        m,bList=0,[]
        for i in range(nProcessors):
                bList.append([i,inPgons,inLines])
        pool = multiprocessing.Pool(nProcessors-1)
        listik=pool.map(function, bList)
##      apply merge here
        print listik
        print ('%i seconds' %(time.time()-t0))

Wyniki, sekundy:

  • normalny lokalny dysk twardy - 191
  • superszybki dysk lokalny - 220
  • dysk sieciowy - 252

Zabawne było to, że zajęło tylko 87 sekund przy użyciu narzędzia geoprzetwarzania od MXD. Być może coś jest nie tak z moim podejściem do łączenia ...

Jak widać, użyłem raczej brzydkiego zapytania FID w (0, 4, 8,12… 500000), aby podzielić zadanie.

Możliwe, że zapytanie oparte na polu wstępnie obliczonym, np. CFIELD = 0, znacznie skróci czas.

Odkryłem również, że czas zgłaszany przez narzędzia do wieloprzetwarzania może się bardzo różnić.

FelixIP
źródło
1
Tak, używasz listy, która zawiera problemy z blokowaniem. Wypróbuj kolejkę multiprocessing.queue. Staraj się również nie zapisywać rzeczy w procesach roboczych, ale utwórz kolejkę wyjściową z danymi, które chcesz zapisać, i pozwól, aby zostało to wykonane przez proces zapisujący.
Benjamin
3

Nie znam PyScriptera, ale jeśli jest on wspierany przez CPython, powinieneś przejść na wieloprocesowość, a nie wielowątkowość, o ile sam problem jest podzielny (jak inni już o nim wspominali).

CPython ma globalną blokadę interpretera , która eliminuje wszelkie korzyści, które może przynieść wiele wątków w twoim przypadku .

Na pewno w innych kontekstach wątki python są przydatne, ale nie w przypadkach, gdy jesteś związany z procesorem.

użytkownik1514631
źródło
1

Moje pytanie brzmi: czy istnieje sposób, aby procesor działał na 100%

Ponieważ procesor ma wiele rdzeni, maksymalnie wykorzystasz rdzeń, na którym działa proces. W zależności od tego, jak skonfigurowałeś swój układ Xeon, będzie on działał do 12 rdzeni (6 fizycznych i 6 wirtualnych z włączonym hyperthreading). Nawet 64-bitowy ArcGIS tak naprawdę nie jest w stanie z tego skorzystać - a to może skutkować ograniczeniami procesora, gdy twój proces jednowątkowy maksymalnie wykorzystuje rdzeń, na którym działa. Potrzebujesz aplikacji wielowątkowej, aby rozłożyć obciążenie na rdzenie LUB (znacznie prościej) możesz zmniejszyć liczbę rdzeni, na których działa procesor, aby zwiększyć przepustowość.

Najprostszym sposobem na zatrzymanie ograniczenia procesora (i upewnienie się, że tak naprawdę jest to ograniczenie procesora, a nie ograniczenia we / wy dysku) jest zmiana ustawień BIOSu dla Xeon i ustawienie go na jeden ogromny rdzeń. Wzrost wydajności będzie znaczny. Pamiętaj tylko, że znacznie zmniejsza to wielozadaniowość twoich komputerów, więc najlepiej, jeśli masz dedykowaną maszynę procesową do jej realizacji. Jest to o wiele prostsze niż próba wielowątkowego kodu - które i tak większość funkcji ArcGIS Desktop (jak w wersji 10.3.1) nie obsługuje.

kingmi
źródło
Jakiego ustawienia należy szukać, aby zmienić procesor w „jeden ogromny pojedynczy rdzeń”?
Alex McVittie,
1
Dokładne menu będzie zależeć od systemu BIOS i oprogramowania układowego układu scalonego, ale zwykle będzie ono dostępne w menu Ustawienia BIOS> Zaawansowane> Konfiguracja procesora. Będziesz chciał wyłączyć hiperwątkowość, a następnie ustawić liczbę rdzeni do aktywacji. 0 to zwykle wszystko - ustaw na 1, jeśli chcesz mieć jeden duży rdzeń. Dobrze jest zanotować ustawienia przed zmianą - brzmi to oczywisto, ale łatwo je przeoczyć, jeśli coś się nie uda.
kingmi