J'ai du code Python conçu pour traiter les fichiers de formes ponctuels via le flux de travail suivant:
- Fusionner des points
- Intégrez des points, de sorte que tous les points situés à moins de 1 m l'un de l'autre deviennent un point
- Créer une couche d'entités, où les points avec z <10 sont sélectionnés
- Points tampons
- Résolution de polygone à raster de 1 m
- Reclassifier, où 1 - 9 = 1; NoData = 0
Chaque fichier de formes contient environ 250 000 à 350 000 points couvrant environ 5 x 7 km. Les données de points utilisées comme entrées représentent les emplacements des arbres. Chaque point (c'est-à-dire un arbre) est associé à une valeur "z" qui représente le rayon de la couronne et est utilisée dans le processus de mise en mémoire tampon. Mon intention est d'utiliser la sortie binaire finale dans un processus séparé pour produire un raster décrivant la couverture de la canopée.
J'ai fait un test avec quatre fichiers de formes et cela a produit une trame de 700 Mo et a pris 35 minutes (processeur i5 et 8 Go de RAM). Étant donné que je devrai exécuter ce processus sur 3500 shapefiles, je vous serais reconnaissant de tout conseil pour rationaliser le processus (voir le code ci-joint). De manière générale, quel est le meilleur moyen de gérer le Big Data avec le géotraitement? Plus précisément, y a-t-il des modifications à apporter au code ou au flux de travail qui pourraient aider à accroître l'efficacité?
modifier :
Temps (% du total) pour les tâches de géotraitement:
- Fusion = 7,6%
- Intégrer = 7.1%
- Fonction à Lyr = 0
- Tampon = 8,8%
- Poly à raster = 74,8%
- Reclassifier = 1.6%
# 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")
la source
Réponses:
Certains changements d'algorithmes devraient vous aider.
Exécutez votre sélection avant la fusion ou l'intégration. Cela réduira considérablement les dernières fonctions les plus coûteuses.
La fusion et l'intégration coûtent cher en mémoire. Vous souhaitez donc continuer à éliminer les fonctionnalités lorsque vous importez des classes d'entités, et essayez d'effectuer vos fusions dans un arbre binaire pour limiter la taille des fusions et des intégrations. par exemple, pour quatre fichiers de formes, vous fusionnez deux fichiers de formes et les intégrez; fusionner deux autres fichiers de formes et les intégrer; fusionner les deux classes d'entités résultantes et les intégrer.
Votre file d'attente commence par une file de références de fichier de formes. Vous avez également une file d'attente de résultats dans laquelle placer les résultats. La méthode run () pour votre agent de traitement parallèle effectue les opérations suivantes: Retirez deux éléments de la file d'attente. Si aucun élément n'est pris (la file d'attente est vide), arrêtez le travailleur. Si un élément est pris, placez-le directement dans la file d'attente des résultats.
Si deux éléments sont pris, pour chaque élément: s'il s'agit d'un fichier de formes, sélectionnez-le pour z <10 et créez une classe d'entités in_memory; sinon, il s'agit déjà d'une classe d'entités in_memory et ignore l'étape de sélection. Fusionnez les deux classes d'entités in_memory pour créer une nouvelle classe d'entités in_memory. Supprimer les deux classes d'entités d'origine. Exécuter intégrer sur la nouvelle classe d'entités. Placez cette classe d'entités dans la file d'attente des résultats.
Puis lancez une boucle while externe. La boucle commence par la file d'attente du fichier de formes et teste une longueur supérieure à 1. Elle exécute ensuite la file d'attente à travers les agents. Si la longueur de la file d'attente de résultats est supérieure à 1, la boucle while exécute un autre traitement parallèle exécuté par les agents jusqu'à ce que la file d'attente soit égale à 1 classe d'entités in_memory.
Par exemple, si vous démarrez avec 3500 fichiers de formes, votre première file d'attente contiendra 3500 tâches. La seconde aura 1750 emplois. 875, 438, 219, 110, 55, 28, 14, 7, 4, 2, 1. Votre gros goulot d'étranglement sera la mémoire. Si vous ne disposez pas de suffisamment de mémoire (et que vous manquerez de mémoire lors de la création de la première file d'attente de résultats si c'est le cas), modifiez votre algorithme pour fusionner plus de 2 classes d'entités à la fois, puis intégrez-le, ce qui réduira la taille de votre première file d'attente de résultats en échange d'un temps de traitement plus long. Vous pouvez éventuellement écrire des fichiers de sortie et ignorer l'utilisation de classes d'entités in_memory. Cela vous ralentira considérablement, mais vous évitera le goulot d'étranglement de la mémoire.
Ce n'est qu'après avoir fusionné et intégré tous les fichiers de formes, en se terminant par une seule classe d'entités, que vous effectuez ensuite la mise en mémoire tampon, poly to raster et reclassification. De cette façon, ces trois opérations ne sont effectuées qu'une seule fois et vous gardez votre géométrie simple.
la source
La première chose que je ferais serait de surveiller l'utilisation des ressources de votre système à l'aide de quelque chose comme Resource Monitor sous Windows 7 ou perfmon sous Vista / XP pour savoir si vous êtes lié au processeur , à la mémoire ou aux E / S. .
Si vous êtes lié à la mémoire ou aux entrées-sorties, vous ne pouvez probablement rien faire d'autre que mettre à niveau le matériel, réduire la taille du problème ou modifier complètement l'approche.
Si vous déterminez que vous êtes lié au processeur, j'expérimenterais le
multiprocessing
module ou l'un des nombreux autres packages de traitement parallèle basés sur Python. disponibles, pour voir si vous pouvez utiliser davantage de cœurs de processeur pour accélérer vos opérations.Le truc pour le multitraitement et le parallélisme en général consiste à trouver un bon schéma de partitionnement qui:
Vous pouvez utiliser le script que j'ai créé dans cette réponse comme point de départ: Portage du code Avenue pour Produire des ombres construites dans ArcPy / Python pour ArcGIS Desktop?
Voir également ce billet de blog ESRI Geoprocessing sur le sujet: Multiprocessing Python - Approches et considérations
Je pense que votre cas va être encore plus difficile en raison de la nature plus "boîte noire" des outils que vous utilisez, plutôt que des tableaux de géométrie à grain plus fin avec lesquels je travaillais. Peut-être que travailler avec des tableaux NumPy peut être utile.
Je suis également tombé sur du matériel de lecture intéressant si vous vouliez aller au-delà de arcpy:
la source