Simplificación del código de Python para Big Data

34

Tengo un código Python que está diseñado para tomar archivos de forma de puntos a través del siguiente flujo de trabajo:

  1. Fusionar puntos
  2. Integre puntos, de modo que cualquier punto dentro de 1 m entre sí se convierta en un punto
  3. Crear capa de entidades, donde se seleccionan puntos con z <10
  4. Puntos de amortiguamiento
  5. Resolución de polígono a ráster de 1 m
  6. Reclasifique, donde 1 - 9 = 1; NoData = 0

Cada archivo de forma tiene aproximadamente 250,000 a 350,000 puntos que cubren ~ 5x7 km. Los datos de puntos utilizados como entradas representan ubicaciones de árboles. Cada punto (es decir, un árbol) tiene un valor "z" asociado que representa el radio de la corona y se utiliza en el proceso de almacenamiento intermedio. Mi intención es utilizar la salida binaria final en un proceso separado para producir un ráster que describa la cubierta del dosel.

Ejecuté una prueba con cuatro archivos de forma y produjo un ráster de 700 MB y tardó 35 minutos (procesador i5 y 8 GB de RAM). Al ver que necesitaré ejecutar este proceso en 3500 shapefiles, agradecería cualquier consejo para simplificar el proceso (ver código adjunto). En términos generales, ¿cuál es la mejor manera de lidiar con el geoprocesamiento de big data? Más específicamente, ¿hay algún ajuste en el código o flujo de trabajo que pueda ayudar a aumentar la eficiencia?

Editar :

Tiempo (% del total) para tareas de geoprocesamiento:

  • Fusionar = 7.6%
  • Integrar = 7.1%
  • Característica para Lyr = 0
  • Tampón = 8.8%
  • Poliéster a ráster = 74.8%
  • Reclasificar = 1.6%

ingrese la descripción de la imagen aquí

# 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")
Aaron
fuente
3
Puede valer la pena poner algún código de tiempo de rendimiento para establecer si la mayor parte del tiempo va en uno o unos pocos pasos, para que esos puedan centrarse en tratar de encontrar ganancias de rendimiento
PolyGeo
55
No creo que tenga muchas opciones para mejorar el rendimiento si sigue usando ArcPy. ¿Quizás puedas mirar otras herramientas para hacer esto? ¿Herramientas como FME o quizás postgis?
tmske
3
No está claro qué tipo de píxel se está utilizando, pero si es "Byte" (que debería ser), entonces el almacenamiento de datos en bruto sería 5000x7000 = 35Mb (~ 33.4MB) por ráster, que en realidad no es tan grande. Sin embargo, la siguiente dimensión de 3500 (¿dimensión de tiempo?) Aumenta el tamaño bruto total a ~ 114 GB.
Mike T
55
Aunque no puedo decir a partir de esta descripción qué está haciendo el algoritmo (o qué pretende hacer), en la mayoría de los casos, los buffers de puntos seguidos de rasterización deben reemplazarse por la rasterización de los puntos seguida de una estadística focal (generalmente una media o suma). El resultado será el mismo pero, al evitar los largos pasos de almacenamiento en búfer y poli rasterización, se obtendrá mucho más rápido. Sospecho (fuertemente) que se podrían obtener aceleraciones adicionales sustanciales, pero no puedo proporcionar consejos específicos debido a la vaguedad de la descripción del procedimiento.
whuber
2
Los búferes alrededor de los puntos son de tamaño variable (en función del valor z del punto). Creo que para hacer estadísticas focales, tendrías que dividir los puntos de resultado por valor z y hacer estadísticas raster y focales en cada conjunto (usando z como radio en un vecindario circular con el máximo como estadística). Luego ejecute Cell Statistics en los 9 rásteres con la estadística máxima para combinar los resultados. (Que probablemente sea mucho más rápido que el búfer y rasterizar con un gran conjunto de datos.)
blord-castillo

Respuestas:

10

Algunos cambios en el algoritmo que deberían ayudarte.

Ejecute su selección primero antes de la fusión o integración. Esto reducirá significativamente las funciones posteriores que son más caras.

Combinar e integrar son costosos para la memoria, por lo que desea seguir eliminando características a medida que incorpora clases de entidades e intentar realizar sus fusiones en un árbol binario para mantener el tamaño de las fusiones e integraciones. por ejemplo, para cuatro shapefiles, fusiona dos shapefiles e integra; fusionar dos shapefiles más e integrar; fusionar las dos clases de entidad resultantes e integrar.

Su cola de trabajos comienza como una cola de referencias de archivos de forma. También tiene una cola de resultados para colocar los resultados. El método run () para su trabajador de procesamiento paralelo realizará estas operaciones: quitar dos elementos de la cola. Si no se toma ningún artículo (la cola está vacía), finalice el trabajador. Si se toma un artículo, colóquelo directamente en la cola de resultados.

Si se toman dos elementos, para cada elemento: si es un archivo de forma, seleccione para z <10 y cree una clase de entidad in_memory; de lo contrario, ya es una clase de entidad in_memory y omite el paso de selección. Combine las dos clases de entidad in_memory para crear una nueva clase de entidad in_memory. Elimine las dos clases de entidad originales. Ejecutar integrar en la nueva clase de entidad. Coloque esa clase de entidad en la cola de resultados.

Luego ejecute un bucle while externo. El bucle comienza con la cola del archivo de forma y prueba una longitud mayor que 1. Luego ejecuta la cola a través de los trabajadores. Si la cola de resultados tiene una longitud mayor que 1, el ciclo while ejecuta otro procesamiento paralelo ejecutado a través de los trabajadores hasta que la cola de resultados sea 1 clase de entidad in_memory.

Por ejemplo, si comienza con 3500 shapefiles, su primera cola tendrá 3500 trabajos. El segundo tendrá 1750 empleos. 875, 438, 219, 110, 55, 28, 14, 7, 4, 2, 1. Su gran cuello de botella será la memoria. Si no tiene suficiente memoria (y se quedará sin memoria en la creación de la primera cola de resultados si ese es el caso), modifique su algoritmo para fusionar más de 2 clases de entidad a la vez e integre, lo que reducirá el tamaño de su primera cola de resultados a cambio de un mayor tiempo de procesamiento. Opcionalmente, puede escribir archivos de salida y omitir usando las clases de entidad in_memory. Esto lo ralentizará considerablemente, pero superaría el cuello de botella de memoria.

Solo después de haber realizado una fusión e integración en todos los archivos de forma, terminando con una sola clase de entidad, entonces realiza el búfer, poli a ráster y reclasifica. De esa forma, esas tres operaciones se realizan solo una vez y usted mantiene su geometría simple.

castillo-blord
fuente
+1 por usar el espacio de trabajo in_memory si sus datos caben en la memoria. Acelera significativamente las operaciones de geoprocesamiento.
RyanDalton
Esto es bueno Creo que podría ser aún mejor con un diagrama y algo de psuedocódigo (¡o código real!).
blah238
Sí, desearía tener algo de tiempo para comprometerme con el código. Necesito escribir un nuevo script de demostración de procesamiento paralelo de todos modos.
blord-castillo
14

Lo primero que haría es monitorear la utilización de recursos de su sistema usando algo como Resource Monitor en Windows 7 o perfmon en Vista / XP para tener una idea de si está vinculado a la CPU , la memoria o IO .

Si tiene un límite de memoria o de E / S, es muy probable que pueda hacer muy poco más que actualizar el hardware, reducir el tamaño del problema o cambiar el enfoque por completo.

Si determina que está vinculado a la CPU, experimentaría con el multiprocessingmódulo, o uno de los muchos otros paquetes de procesamiento paralelo basados ​​en Python disponibles, para ver si puede usar más núcleos de CPU para acelerar sus operaciones.

El truco para el multiprocesamiento y el paralelismo en general es encontrar un buen esquema de partición que:

  1. Le permite dividir las entradas en conjuntos de trabajo más pequeños, luego recombinar los resultados de una manera que tenga sentido,
  2. Agrega la menor cantidad de gastos generales (algunos son inevitables en comparación con el procesamiento en serie), y
  3. Le permite ajustar el tamaño del conjunto de trabajo para utilizar mejor los recursos del sistema para un rendimiento óptimo.

Puede usar el script que creé en esta respuesta como punto de partida: ¿ Portar el código de Avenue para producir Building Shadows en ArcPy / Python for ArcGIS Desktop?

Consulte también esta publicación de blog de geoprocesamiento de ESRI sobre el tema: Multiprocesamiento de Python: enfoques y consideraciones

Creo que su caso será aún más desafiante debido a la naturaleza más "caja negra" de las herramientas que está utilizando, en lugar de las matrices de geometría más finas con las que estaba trabajando. Quizás trabajar con matrices NumPy pueda ser útil.

También encontré material de lectura interesante si querías mirar más allá de arcpy:

blah238
fuente