Modi per velocizzare gli script Python in esecuzione come strumenti ArcGIS [chiuso]


31

Questa è una domanda piuttosto generica. Mi chiedo solo quali suggerimenti e trucchi hanno usato i programmatori GIS per accelerare gli script arcpy che importi nella toolbox ed esegui.

Lavoro quasi tutti i giorni scrivendo piccoli script per aiutare gli utenti non GIS nel mio ufficio a elaborare i dati GIS. Ho scoperto che l'elaborazione ArcGIS 10.0 in generale è più lenta della 9.3.1 e talvolta diventa ancora più lenta quando si esegue uno script Python.

Elencherò un esempio particolare di uno script che impiega più di 24 ore per l'esecuzione. È un loop che tabula l'area di un raster in un buffer per ogni forma nel buffer. Il buffer ha circa 7000 forme. Non credo che dovrebbe durare così a lungo. UN

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

Prima che qualcuno lo dica, ho eseguito l'area tabulate sull'intero buffer, ma produce errori se eseguito su più di 1 record. È uno strumento imperfetto, ma devo usarlo.

Ad ogni modo, se qualcuno ha qualche idea su come ottimizzare o velocizzare questo script, sarebbe molto apprezzato. Altrimenti, hai qualche trucco per accelerare per Python, quando usato in ArcGIS?

Risposte:


26

Un paio di potenziali suggerimenti per velocizzare il processo sono:

  1. Seleziona livello per attributo può essere in uno script solo Python, senza mai avviare ArcGIS Desktop. È necessario convertire il riferimento "buff" da un riferimento basato su file a un riferimento "livello ArcGIS", contro il quale ArcGIS può elaborare le query di selezione. Usa arcpy.MakeFeatureLayer_management ("buff", "buff_lyr") sopra il tuo ciclo "while", quindi cambia i riferimenti sotto il ciclo while per usare "buff_lyr".

  2. Elaborare la maggior parte delle operazioni GP utilizzando l' area di lavoro in_memory possibile ... Utilizzare arcpy.CopyFeatures_management (shapefile, "in_memory \ memFeatureClass") per spostare l'origine in memoria. Funziona bene solo se hai abbastanza RAM per leggere tutte le classi di funzionalità di cui hai bisogno in memoria. Attenzione, tuttavia, che ci sono alcune operazioni GP che non possono essere eseguite utilizzando l'area di lavoro in_memory (ad esempio: lo strumento Progetto).

Dall'articolo della guida in linea di ArcGIS 9.3 " Dati intermedi e area di lavoro scratch " (si noti che questa lingua è stata rimossa dalla guida 10.0 e 10.1):

NOTA: solo le tabelle e le classi di entità geografiche (punti, linee, poligoni) possono essere scritte nell'area di lavoro in_memory. L'area di lavoro in_memory non supporta elementi di geodatabase estesi come sottotipi, domini, rappresentazioni, topologie, reti geometriche e set di dati di rete. È possibile scrivere solo funzioni e tabelle semplici.

Dall'articolo della guida in linea di ArcGIS 10.1 " Utilizzo dell'area di lavoro in memoria ":

Le seguenti considerazioni devono essere fatte nel decidere di scrivere l'output nell'area di lavoro in memoria:

  • I dati scritti nell'area di lavoro in memoria sono temporanei e verranno eliminati alla chiusura dell'applicazione.
  • Tabelle, classi di entità geografiche e raster possono essere scritti nell'area di lavoro in memoria.
  • L'area di lavoro in memoria non supporta elementi di geodatabase estesi come sottotipi, domini, rappresentazioni, topologie, reti geometriche e set di dati di rete.
  • I set di dati o le cartelle delle funzioni non possono essere creati nell'area di lavoro in memoria.

1
È fantastico! Ho cercato un modo per utilizzare le selezioni al di fuori di ArcMap, ma finora non ho avuto successo. In termini di questo problema, in realtà ha ridotto il mio tempo per riga a circa 13 secondi da 20 secondi. Ma ho fatto un altro rapido giro e ho fatto MakeFeatureLayer all'interno del loop ed è sceso a 9 secondi. L'ho fatto creando una feature per ogni forma piuttosto che tabulando dal feature layer. Vorrei ancora abbassarlo ulteriormente, se possibile, ma già è un processo molto più veloce!
Cody Brown,

Come menzionato nel n. 2, usa le funzioni Copia per creare una copia dei tuoi dati sorgente in_memory, quindi crea il tuo feature_layer sulla fonte in_memory. Mentre la copia iniziale in memoria può aggiungere un paio di secondi in anticipo, potresti scoprire che quell'elaborazione di funzionalità di copia + tabulate_areas ha un tempo di elaborazione totale più veloce rispetto al tuo modello attuale.
Ryan Dalton,

Ho provato anche quello e sembra che quella soluzione renderebbe il processo del ciclo più veloce ma non lo fa. La creazione del feature layer nel loop comporta circa 8-10 secondi per loop, mentre la creazione del feature layer prima del loop comporta 11-14 secondi per loop. Non sono troppo sicuro del perché, dato che la tua soluzione sembra elaborarsi più velocemente. Ho 8 GB di RAM, quindi dubito che sarebbe il problema.
Cody Brown,

Copiare anche le funzionalità in in_memory prima del loop e quindi creare il layer delle funzionalità nel loop produce prestazioni leggermente più veloci. Rimane praticamente un 8 secondi per riga per ogni ciclo. Il che farà scendere il tempo totale di processo da 26 ore a 22.
Cody Brown

Dopo aver aggiunto le tue idee, la mia sceneggiatura è notevolmente migliorata. Grazie mille per il tuo e l'aiuto di tutti!
Cody Brown,

28

Le tecniche generali di ottimizzazione di Python possono farti risparmiare notevoli quantità di tempo.

Una tecnica davvero buona per capire come si trovano i blocchi nel tuo script è usare il modulo cProfile integrato:

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

Il test con un piccolo campione di dati ti permetterà di individuare quali chiamate di funzione impiegano più tempo.

Puntatori generali per un codice Python più veloce:

  • La comprensione dell'elenco è generalmente più rapida del looping
  • I generatori producono un articolo alla volta anziché produrre l'intero elenco in una volta
  • Usa xrange invece di range in python 2 (non necessario in 3)
  • Imposta possibile fuori le liste di preforme quando si tratta di determinare se un elemento è presente nel set, ma sono generalmente più lento di liste quando si tratta di iterazione di loro contenuto Fonte
  • Le chiamate di funzione possono essere costose per la fonte delle prestazioni
  • Ulteriori suggerimenti e dettagli sono disponibili qui Suggerimenti per le prestazioni Python e qui 10 Suggerimenti e problemi per l'ottimizzazione di Python

Per quanto riguarda il tuo script, non posso commentare gli aspetti di ArcPy poiché non ho Arc installato su questo computer, ma potresti voler provare a usare un ciclo for anziché un ciclo while per vedere se questo migliora qualcosa. Inoltre x = x + 1 può essere scritto come 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

1
Ho usato i due link che hai lasciato sul tuo ultimo proiettile e sono stato in grado di aiutare davvero il mio script con alcune correzioni rapide!
Cody Brown,

Se potessi assegnare due risposte corrette lo farei. Mentre la tua risposta ha offerto davvero molte idee su come velocizzare Python, @RyanDalton ha offerto l'idea che ha avuto il maggiore impatto. Grazie mille!
Cody Brown,

13

Assicurati di scrivere sull'unità interna del computer. Raggiungere attraverso la rete quando non è necessario può davvero rallentare l'elaborazione. Può anche essere più veloce copiare i dati come primo passo del processo per mantenere le successive scritture in lettura il più rapidamente possibile

L'esecuzione dello script completamente al di fuori di ArcMap può essere molto più veloce. Se durante l'elaborazione non è richiesta una mappa, non utilizzare ArcMap.


Ho scoperto che l'esecuzione di uno script all'interno di un modello da ArcCatalog (di per sé all'interno di una Calculate Valuefinestra di dialogo) verrà elaborata più rapidamente rispetto all'esecuzione dello stesso script dalla finestra ArcPy in ArcMap. Questa è puramente un'osservazione aneddotica.
Cindy Jayakumar,

1
Credo di aver bisogno di una mappa per il corretto funzionamento di Tabulate, ma ci proverò. Se funziona al di fuori di ArcMap, scommetto che accelererebbe. Inoltre sto già correndo dal disco locale, che ha già raddoppiato la velocità dello script.
Cody Brown,

Purtroppo il Select non funziona al di fuori di ArcMap ed è necessario perché devo fare il tabulato forma per forma.
Cody Brown,

3
@ CodyBrown: non sei corretto su Select non funziona al di fuori di una sessione ArcMap. Vedi la mia risposta sull'uso dello strumento MakeFeatureLayer.
Ryan Dalton,

Ryan ha ragione. Quando lo strumento di selezione viene utilizzato da solo, crea una vista tabella dei dati spaziali o dei dati della tabella. Quando lo usi in ModelBuilde o in uno script, devi creare una vista e, nel tuo caso, crearla utilizzando lo strumento MakeFeatureLayer.
dchaboya,

6

Questo potrebbe non rispondere alla tua domanda per l'esecuzione degli strumenti ArcPy all'interno di ArcMap, ma quando ho bisogno di eseguire alcune elaborazioni elaborate con strumenti di geo-elaborazione e Python, tendo a eseguirlo al di fuori del sistema GIS utilizzando l'IDE PyScripter . Ho scoperto che corre più veloce. Ho anche utilizzato un RAMDISK per piccoli set di dati di output temporanei (un po 'come l' area di lavoro in_memory )

Bene, sono i miei migliori consigli! :)


2
Per confondere in qualche modo questa risposta, quando si eseguono script da IDE Python molti iniettano una funzione di traceback per aiutare a guardare le variabili e altri vari aiuti di debug. Questa funzione può rallentare enormemente gli script se fa troppo come viene chiamata TUTTO IL TEMPO, e talvolta questo viene installato implicitamente senza l'intervento dell'utente. Si è verificato un caso patologico particolare in cui uno script Python eseguito in ArcMap è stato eseguito in 4 minuti, mentre lo stesso script di Wing IDE ha richiesto 3 ore. Non appena è stato eseguito da Python.exe senza Wing, è tornato al territorio di runtime di ~ 2-3 minuti.
Jason Scheirer,

1
avevo mal di testa per sintonizzare i miei script su ArMap, a volte non posso completamente, fino a quando non mi sono rivolto a Pyscripter, può ridurre i tempi di esecuzione rispetto ad Arcmap, senza usare alcun suggerimento di ottimizzazione.
geogeek,

@JasonScheirer hai trovato il tweak in Wing per disattivarlo? Sono sicuro che ce n'è uno.
Curtis Price,

5

Prova a commentare arcpy.SetProgressorLabel e vedi quanto acceleri. Ho scoperto che qualsiasi output dello schermo, tornando al daze DOS, rallenta drasticamente i tempi di elaborazione. Se hai davvero bisogno di vedere quell'output, prova a mostrarlo ogni ennesimo loop.


4

Assicurati di rimuovere tutte le import xxxxrighe che non vengono utilizzate.

(ad es. se non stai ancora utilizzando alcuna funzione matematica import Math, ciò richiederà del tempo dal caricamento dello script)

Anche se questo non avrà un grande impatto sui singoli script eseguiti (come il tuo), avrà effetto su tutti gli script eseguiti frequentemente e ripetutamente.


7
Dubito che qualsiasi modulo Python standard impieghi più di un millesimo del tempo necessario per inizializzare il modulo arcpy.
blah238,

1
@ blah238 è import Mathstato probabilmente un cattivo esempio. Alcune delle più grandi librerie ArcPy, tuttavia, impiegano molto tempo a caricarsi.
nagytech,

1
questo continua a radersi solo pochi secondi (al massimo!), non ore
Mike T

1
@MikeToews Per gli script che vengono eseguiti frequentemente e ripetutamente, alcuni secondi si sommano nel corso di alcuni giorni / settimane ecc. Sebbene ciò non risolva il problema principale dell'OP, ha chiesto suggerimenti generali.
nagytech,
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.