Formas de acelerar las secuencias de comandos de Python que se ejecutan como herramientas ArcGIS [cerrado]

31

Esta es una pregunta bastante general. Me pregunto qué consejos y trucos han utilizado los programadores de SIG para acelerar los scripts arcpy que importas a la caja de herramientas y ejecutas.

Trabajo casi todos los días escribiendo pequeños scripts para ayudar a los usuarios que no son SIG en mi oficina a procesar datos SIG. He descubierto que el procesamiento de ArcGIS 10.0 en general es más lento que 9.3.1 y, a veces, se vuelve aún más lento cuando se ejecuta un script de Python.

Voy a enumerar un ejemplo particular de un script que tarda más de 24 horas en ejecutarse. Es un bucle que tabula el área de un ráster en un búfer para cada forma en el búfer. El búfer tiene aproximadamente 7000 formas. No creo que deba durar tanto. UNA

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

Antes de que alguien lo diga, ejecuté el área de tabulación en todo el búfer, pero produce errores si se ejecuta en más de 1 registro. Es una herramienta defectuosa, pero tengo que usarla.

De todos modos, si alguien tiene alguna idea sobre cómo optimizar o acelerar este script, sería muy apreciado. De lo contrario, ¿tiene algún truco para acelerar Python cuando se usa en ArcGIS?

Cody Brown
fuente

Respuestas:

26

Algunas sugerencias potenciales para ayudar a acelerar su proceso son:

  1. Seleccionar capa por atributo puede estar en un script solo para Python, sin tener que iniciar ArcGIS Desktop. Debe convertir su referencia de "beneficio" de una referencia basada en archivo a una referencia de "capa ArcGIS", con la cual ArcGIS puede procesar consultas de selección. Use arcpy.MakeFeatureLayer_management ("buff", "buff_lyr") encima de su ciclo "while", y luego cambie sus referencias debajo del ciclo while para usar "buff_lyr".

  2. Procese la mayor cantidad de operaciones de GP utilizando el espacio de trabajo in_memory como sea posible ... Use arcpy.CopyFeatures_management (shapefile, "in_memory \ memFeatureClass") para mover su fuente a la memoria. Esto solo funciona bien si tiene suficiente RAM para leer todas las clases de entidad que necesita en la memoria. Sin embargo, tenga en cuenta que hay algunas operaciones GP que no pueden ejecutarse utilizando el espacio de trabajo in_memory (por ejemplo: la herramienta Proyecto).

Del artículo de ayuda en línea de ArcGIS 9.3 " Datos intermedios y el espacio de trabajo temporal " (tenga en cuenta que este idioma se eliminó de la ayuda 10.0 y 10.1):

NOTA: Solo las tablas y las clases de entidad (puntos, líneas, polígonos) se pueden escribir en el espacio de trabajo in_memory. El espacio de trabajo in_memory no admite elementos de geodatabase extendidos, como subtipos, dominios, representaciones, topologías, redes geométricas y conjuntos de datos de red. Solo se pueden escribir características y tablas simples.

Del artículo de ayuda en línea ArcGIS 10.1 " Uso del espacio de trabajo en memoria "

Deben hacerse las siguientes consideraciones al decidir escribir la salida en el espacio de trabajo en memoria:

  • Los datos escritos en el espacio de trabajo en memoria son temporales y se eliminarán cuando se cierre la aplicación.
  • Las tablas, las clases de entidad y los rásteres se pueden escribir en el espacio de trabajo en memoria.
  • El espacio de trabajo en memoria no admite elementos de geodatabase ampliados, como subtipos, dominios, representaciones, topologías, redes geométricas y conjuntos de datos de red.
  • Los conjuntos de datos o carpetas de entidades no se pueden crear en el espacio de trabajo en memoria.
RyanDalton
fuente
1
¡Eso es fantástico! He estado buscando una forma de usar selecciones fuera de ArcMap, pero hasta ahora no había tenido éxito. En términos de este problema, en realidad redujo mi tiempo por fila a unos 13 segundos desde 20 segundos. Pero, hice otro trabajo rápido e hice MakeFeatureLayer dentro del ciclo y bajó a 9 segundos. Lo hice creando una entidad de cada forma que tabulando desde la capa de entidades. Todavía me gustaría bajar más si es posible, ¡pero ya es un proceso mucho más rápido!
Cody Brown
Como se menciona en el n. ° 2, use CopyFeatures para hacer una copia de sus datos de origen en_memory, luego cree su feature_layer contra el origen de in_memory. Si bien la copia inicial en la memoria puede agregar un par de segundos por adelantado, es posible que ese procesamiento de copyfeatures + tabulate_areas tenga un tiempo de procesamiento total más rápido que su modelo actual.
RyanDalton
Intenté eso también y parece que esa solución aceleraría el proceso del ciclo, pero no lo hace. La creación de la capa de entidades en el bucle da como resultado unos 8-10 segundos por bucle, mientras que la creación de la capa de entidades antes del bucle da como resultado de 11 a 14 segundos por bucle. No estoy muy seguro de por qué, ya que su solución parece que se procesaría más rápido. Tengo 8 GB de RAM, así que dudo que ese sea el problema.
Cody Brown
También hacer frente a las características en in_memory antes del bucle y luego seguir creando la capa de entidades en el bucle resulta en un rendimiento ligeramente más rápido. Se queda más o menos 8 segundos por fila para cada ciclo. Lo que reducirá el tiempo total del proceso de 26 horas a 22.
Cody Brown
Después de agregar sus ideas, mi script mejoró dramáticamente. ¡Muchas gracias por la suya y la ayuda de todos!
Cody Brown el
28

Las técnicas generales de optimización de Python pueden ahorrarle una cantidad considerable de tiempo.

Una técnica realmente buena para obtener un resumen de dónde están las retenciones en su script es usar el módulo cProfile incorporado:

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

La prueba con una pequeña muestra de datos le permitirá determinar qué llamadas de función están tomando más tiempo.

Punteros generales para un código python más rápido:

  • Las comprensiones de listas son generalmente más rápidas que los bucles
  • Los generadores producen un artículo a la vez en lugar de producir la lista completa a la vez
  • Use xrange en lugar de range en python 2 (no es necesario en 3)
  • Los conjuntos pueden salir listas de preforma cuando se trata de determinar si un elemento está presente en el set, pero son generalmente más lento que las listas cuando se trata de iterar sobre su contenido Fuente
  • Las llamadas a funciones pueden ser costosas para el rendimiento Fuente
  • Más consejos y detalles, consulte aquí Consejos de rendimiento de Python y aquí 10 consejos y problemas de optimización de Python

Con respecto a su secuencia de comandos, no puedo comentar sobre los aspectos de ArcPy ya que no tengo Arc instalado en esta computadora, pero es posible que desee intentar usar un bucle for en lugar de un bucle while para ver si eso mejora algo. También x = x + 1 se puede escribir como 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
fuente
1
¡Utilicé los dos enlaces que dejaste en tu última viñeta y pude realmente ayudar a mi script con algunas soluciones rápidas!
Cody Brown
Si pudiera otorgar dos respuestas correctas, lo haría. Si bien su respuesta realmente ofreció muchas ideas sobre cómo acelerar Python, @RyanDalton ofreció las ideas que tuvieron el mayor impacto. ¡Gracias una tonelada!
Cody Brown el
13

Asegúrese de escribir en la unidad interna de la computadora. Llegar a través de la red cuando no es necesario realmente puede retrasar el procesamiento. Incluso puede ser más rápido copiar los datos como el primer paso en el proceso para mantener las lecturas y escrituras posteriores lo más rápido posible

Ejecutar el script completamente fuera de ArcMap puede ser mucho más rápido. Si no se requiere un mapa durante el procesamiento, no use ArcMap.

mhoran_psprep
fuente
Descubrí que ejecutar un script dentro de un modelo desde ArcCatalog (solo dentro de un Calculate Valuecuadro de diálogo) se procesará más rápido que ejecutar el mismo script desde la ventana ArcPy en ArcMap. Sin embargo, eso es puramente una observación anecdótica.
Cindy Jayakumar
1
Creo que necesito un mapa para que Tabulate funcione correctamente, pero voy a intentarlo. Si funciona fuera de ArcMap, apuesto a que se aceleraría. Además, ya estoy ejecutando el disco local, que ya duplicó la velocidad del script.
Cody Brown el
Lamentablemente, Select no funciona fuera de ArcMap y es necesario porque necesito hacer la tabulación forma por forma.
Cody Brown
3
@ CodyBrown: es incorrecto acerca de que Select no funciona fuera de una sesión de ArcMap. Vea mi respuesta sobre el uso de la herramienta MakeFeatureLayer.
RyanDalton
Ryan tiene razón. Cuando la herramienta de selección se utiliza por sí sola, crea una vista de tabla de sus datos espaciales o datos de tabla. Al usarlo en ModelBuilde o en un script, debe crear una vista y, en su caso, crearla utilizando la herramienta MakeFeatureLayer.
dchaboya
6

Es posible que esto no responda a su pregunta para ejecutar las herramientas de ArcPy dentro de ArcMap, pero cuando necesito hacer un procesamiento con mucha carne con herramientas de procesamiento geográfico y Python, tiendo a ejecutarlo fuera del sistema SIG utilizando el IDE PyScripter . He encontrado que corre más rápido. También he empleado un RAMDISK para pequeños conjuntos de datos de salida temporales (un poco como el espacio de trabajo in_memory )

Bueno, ellos son mis mejores consejos! :)

Hornbydd
fuente
2
Para enturbiar esta respuesta, cuando se ejecutan secuencias de comandos desde IDE de Python, muchos inyectan una función de rastreo para ayudar a observar variables y otras diversas ayudas de depuración. Esta función puede ralentizar enormemente los scripts si hace demasiado, ya que se llama TODO EL TIEMPO, y a veces esto se instala implícitamente sin la intervención del usuario. Observé un caso patológico particular en el que se ejecutó un script Python en ArcMap en 4 minutos, mientras que el mismo script de Wing IDE tardó 3 horas. Tan pronto como se ejecutó desde Python.exe sin Wing, volvió al territorio de tiempo de ejecución de ~ 2-3 minutos.
Jason Scheirer
1
Estaba teniendo dolor de cabeza para ajustar mis scripts en ArMap, a veces no puedo por completo, hasta que recurrí a Pyscripter, puede reducir el tiempo de ejecución en comparación con Arcmap, sin usar ningún consejo de optimización.
geogeek
@JasonScheirer, ¿encontraste el ajuste en Wing para desactivar esto? Estoy seguro de que hay uno.
Curtis Precio
5

Intente comentar arcpy.SetProgressorLabel y vea cuánto acelera. Descubrí que cualquier salida de pantalla, volviendo al aturdimiento de DOS, ralentiza drásticamente los tiempos de procesamiento. Si realmente necesita ver esa salida, intente mostrarla en cada enésimo bucle.

usuario30749
fuente
4

Asegúrese de eliminar cualquier import xxxx línea que no se esté utilizando.

(es decir, si no está utilizando ninguna función matemática todavía tiene import Math , esto llevará algún tiempo desde la carga del script)

Aunque esto no tendrá un gran impacto en las secuencias de comandos individuales que se ejecutan (como la suya), afectará a las secuencias de comandos que se ejecutan con frecuencia y de forma repetitiva.

nagytech
fuente
77
Dudo que cualquier módulo Python estándar tarde más de una milésima parte del tiempo que tarda el módulo arcpy en inicializarse.
blah238
1
@ blah238 import Mathfue probablemente un mal ejemplo. Sin embargo, algunas de las bibliotecas ArcPy más grandes tardan una cantidad considerable de tiempo en cargarse.
nagytech
1
esto todavía se reduce solo unos segundos (¡a lo sumo!), no horas
Mike T
1
@MikeToews Para los scripts que se ejecutan con frecuencia y de forma repetitiva, se acumulan unos segundos en el transcurso de unos días / semanas, etc. Aunque esto no resuelve el problema principal del OP, solicitó consejos generales.
nagytech