Semplificazione del codice Python per Big Data


34

Ho il codice Python che è progettato per prendere forma shapefile attraverso il seguente flusso di lavoro:

  1. Unisci punti
  2. Integrare punti, in modo tale che tutti i punti entro 1 m l'uno dall'altro diventino un punto
  3. Crea feature layer, in cui sono selezionati punti con z <10
  4. Punti buffer
  5. Poligono a raster con risoluzione 1m
  6. Riclassifica, dove 1 - 9 = 1; NoData = 0

Ogni file di forma ha circa 250.000 a 350.000 punti che coprono ~ 5x7 km. I dati dei punti utilizzati come input rappresentano le posizioni dell'albero. Ogni punto (cioè albero) ha un valore "z" associato che rappresenta il raggio della corona e viene utilizzato nel processo del buffer. Il mio intento è quello di utilizzare l'output binario finale in un processo separato per produrre un raster che descriva la copertura del baldacchino.

Ho eseguito un test con quattro shapefile e ha prodotto un raster da 700 MB e ha impiegato 35 minuti (processore i5 e 8 GB di RAM). Visto che dovrò eseguire questo processo su 3500 shapefile, apprezzerei qualsiasi consiglio per semplificare il processo (vedi codice allegato). In generale, qual è il modo migliore per gestire i big data di geoprocessing? Più specificamente, ci sono delle modifiche al codice o al flusso di lavoro che potrebbero aiutare ad aumentare l'efficienza?

Edit :

Tempo (% del totale) per le attività di geoprocessing:

  • Unisci = 7,6%
  • Integrare = 7,1%
  • Caratteristica per Lyr = 0
  • Buffer = 8,8%
  • Da Poly a Raster = 74,8%
  • Riclassifica = 1,6%

inserisci qui la descrizione dell'immagine

# Import arcpy module
import arcpy

# Check out any necessary licenses
arcpy.CheckOutExtension("spatial")

# Script arguments
temp4 = arcpy.GetParameterAsText(0)
if temp4 == '#' or not temp4:
    temp4 = "C:\\gdrive\\temp\\temp4" # provide a default value if unspecified

Reclassification = arcpy.GetParameterAsText(1)
if Reclassification == '#' or not Reclassification:
    Reclassification = "1 9 1;NODATA 0" # provide a default value if unspecified

Multiple_Value = arcpy.GetParameterAsText(2)
if Multiple_Value == '#' or not Multiple_Value:
    Multiple_Value = "C:\\t1.shp;C:\\t2.shp;C:\\t3.shp;C:\\t4.shp" # provide a default value if unspecified

# Local variables:
temp_shp = Multiple_Value
Output_Features = temp_shp
temp2_Layer = Output_Features
temp_Buffer = temp2_Layer
temp3 = temp_Buffer

# Process: Merge
arcpy.Merge_management(Multiple_Value, temp_shp, "x \"x\" true true false 19 Double 0 0 ,First,#,C:\\#########omitted to save space

# Process: Integrate
arcpy.Integrate_management("C:\\gdrive\\temp\\temp.shp #", "1 Meters")

# Process: Make Feature Layer
arcpy.MakeFeatureLayer_management(temp_shp, temp2_Layer, "z <10", "", "x x VISIBLE NONE;y y VISIBLE NONE;z z VISIBLE NONE;Buffer Buffer VISIBLE NONE")

# Process: Buffer
arcpy.Buffer_analysis(temp2_Layer, temp_Buffer, "z", "FULL", "ROUND", "NONE", "")

# Process: Polygon to Raster
arcpy.PolygonToRaster_conversion(temp_Buffer, "BUFF_DIST", temp3, "CELL_CENTER", "NONE", "1")

# Process: Reclassify
arcpy.gp.Reclassify_sa(temp3, "Value", Reclassification, temp4, "DATA")

3
Potrebbe valere la pena inserire un codice di temporizzazione delle prestazioni per stabilire se la maggior parte del tempo sta andando in uno o pochi passaggi, in modo che quelli possano essere focalizzati su per cercare di trovare miglioramenti delle prestazioni
PolyGeo

5
Non credo che tu abbia molte opzioni per migliorare le prestazioni se continui ad usare ArcPy. Forse puoi guardare altri strumenti per farlo? Strumenti come FME o forse postgis?
tmske,

3
Non è chiaro quale tipo di pixel viene utilizzato, ma se è "Byte" (quale dovrebbe essere), la memorizzazione dei dati grezzi sarebbe 5000x7000 = 35 Mb (~ 33,4 MB) per raster, che in realtà non è così grande. Tuttavia, la dimensione successiva di 3500 (dimensione temporale?) Aumenta la dimensione grezza totale a ~ 114 GB.
Mike T,

5
Sebbene da questa descrizione non possa dire cosa stia facendo (o intendesse fare) l'algoritmo, nella maggior parte dei casi i buffer dei punti seguiti dalla rasterizzazione dovrebbero essere sostituiti dalla rasterizzazione dei punti seguita da una statistica focale (di solito una media o somma). Il risultato sarà lo stesso ma, evitando le lunghe fasi di buffering e polimerizzazione, sarà ottenuto molto più velocemente. Sospetto (fortemente) che si possano ottenere sostanziali ulteriori accelerazioni, ma non posso fornire consigli specifici a causa della vaghezza della descrizione della procedura.
whuber

2
I buffer attorno ai punti hanno dimensioni variabili (in base al valore z del punto). Penso che per fare ancora statistiche focali, dovresti dividere i punti risultato in base al valore z e fare statistiche raster e focali su ogni set (usando z come raggio su un quartiere circolare con massimo come stat). Quindi esegui Cell Statistics su tutti e 9 i raster con la stat massima per unire i risultati. (Che probabilmente è ancora molto più veloce del buffer e rasterizza con un grande set di dati.)
blord-castillo

Risposte:


10

Alcune modifiche all'algoritmo che dovrebbero esserti utili.

Esegui la selezione prima di unire o integrare. Ciò ridurrà significativamente le funzioni successive più costose.

Unire e integrare sono entrambi costosi dalla memoria, quindi si desidera continuare a eliminare le funzionalità quando si introducono le classi di funzionalità e si tenta di eseguire le fusioni in un albero binario per mantenere le dimensioni delle fusioni e delle integrazioni verso il basso. ad esempio per quattro shapefile si uniscono due shapefile e si integrano; unire altri due shapefile e integrarli; unire le due classi di caratteristiche risultanti e integrarle.

La coda dei lavori inizia come una coda di riferimenti shapefile. Hai anche una coda di risultati in cui inserire i risultati. Il metodo run () per il lavoratore dell'elaborazione parallela eseguirà queste operazioni: Rimuovere due elementi dalla coda. Se non viene preso alcun elemento (la coda è vuota), termina il lavoratore. Se viene preso un oggetto, inseriscilo direttamente nella coda dei risultati.

Se vengono presi due elementi, per ogni elemento: se si tratta di un file di forma, selezionare per z <10 e creare una classe di caratteristiche in_memory; altrimenti, è già una feature class in_memory e salta il passaggio di selezione. Unire le due classi di caratteristiche in_memory per creare una nuova classe di caratteristiche in_memory. Elimina le due classi di funzioni originali. Eseguire l'integrazione sulla nuova classe di funzionalità. Inserire quella classe di funzionalità nella coda dei risultati.

Quindi eseguire un ciclo while esterno. Il ciclo inizia con la coda dello shapefile e verifica una lunghezza maggiore di 1. Quindi esegue la coda attraverso i lavoratori. Se la coda dei risultati ha una lunghezza maggiore di 1, il ciclo while esegue un'altra elaborazione parallela eseguita attraverso i lavoratori fino a quando la coda dei risultati è 1 classe di caratteristiche in_memory.

ad es. Se inizi con 3500 shapefile, la tua prima coda avrà 3500 lavori. Secondo avrà 1750 posti di lavoro. 875, 438, 219, 110, 55, 28, 14, 7, 4, 2, 1. Il tuo grande collo di bottiglia sarà la memoria. Se non si dispone di memoria sufficiente (e si esaurisce la memoria nella creazione della prima coda dei risultati, in tal caso), quindi modificare l'algoritmo per unire più di 2 classi di funzioni contemporaneamente, quindi integrare, che ridurrà la dimensione della prima coda dei risultati in cambio di tempi di elaborazione più lunghi. Facoltativamente, è possibile scrivere file di output e saltare utilizzando le classi di caratteristiche in_memory. Questo ti rallenterà considerevolmente, ma supererebbe il collo di bottiglia della memoria.

Solo dopo aver eseguito l'unione e l'integrazione su tutti i file di forma, terminando con una singola classe di feature, si esegue quindi il buffer, da poly a raster e la riclassificazione. In questo modo queste tre operazioni vengono eseguite una sola volta e si mantiene semplice la geometria.


+1 per l'utilizzo dell'area di lavoro in_memory se i tuoi dati si adatteranno alla memoria. Accelera notevolmente le operazioni di geoprocessing.
Ryan Dalton,

Questa è roba buona. Penso che potrebbe essere ancora meglio con un diagramma e un po 'di psuedocode (o codice reale!).
blah238,

Sì, vorrei avere un po 'di tempo per impegnarmi nel codice. Devo comunque scrivere un nuovo script demo di elaborazione parallela.
blord-castillo,

14

La prima cosa che vorrei fare è monitorare l'utilizzo delle risorse del tuo sistema usando qualcosa come Resource Monitor in Windows 7 o perfmon in Vista / XP per avere un'idea del fatto che tu sia CPU , memoria o IO-bound .

Se sei legato alla memoria o all'IO, probabilmente c'è molto poco che puoi fare se non aggiornare l'hardware, ridurre le dimensioni del problema o cambiare completamente l'approccio.

Se determini che sei associato alla CPU, sperimenterei il multiprocessingmodulo o uno dei tanti altri pacchetti di elaborazione parallela basati su Python disponibili, per vedere se puoi usare più core della CPU per velocizzare le tue operazioni.

Il trucco del multiprocessing e del parallelismo in generale è trovare un buon schema di partizionamento che:

  1. Ti consente di suddividere gli input in gruppi di lavoro più piccoli, quindi ricombinare i risultati in modo sensato,
  2. Aggiunge la minima quantità di overhead (alcuni sono inevitabili rispetto all'elaborazione seriale) e
  3. Consente di regolare le dimensioni del working set per utilizzare al meglio le risorse del sistema per prestazioni ottimali.

È possibile utilizzare lo script che ho creato in questa risposta come punto di partenza: codice Porting Avenue per la produzione di ombre da costruzione su ArcPy / Python per ArcGIS Desktop?

Vedi anche questo post sul blog di Geoprocessing ESRI sull'argomento: Python Multiprocessing - Approcci e considerazioni

Penso che il tuo caso sarà ancora più impegnativo a causa della natura più "black box" degli strumenti che stai utilizzando, piuttosto che delle matrici di geometria a grana più fine con cui stavo lavorando. Forse lavorare con gli array NumPy può tornare utile.

Mi sono anche imbattuto in materiale di lettura interessante se volevi guardare oltre arcpy:

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.