Merampingkan Kode Python untuk Data Besar

34

Saya memiliki kode Python yang dirancang untuk mengambil titik shapefile melalui alur kerja berikut:

  1. Gabungkan poin
  2. Mengintegrasikan poin, sehingga setiap titik dalam 1 m satu sama lain menjadi satu poin
  3. Buat layer Fitur, di mana titik dengan z <10 dipilih
  4. Poin Buffer
  5. Resolusi Polygon to raster 1m
  6. Reklasifikasi, di mana 1 - 9 = 1; NoData = 0

Setiap shapefile memiliki sekitar 250.000 hingga 350.000 titik yang mencakup ~ 5x7 km. Data titik yang digunakan sebagai input mewakili lokasi pohon. Setiap titik (yaitu pohon) memiliki nilai "z" yang terkait yang mewakili radius mahkota dan digunakan dalam proses buffer. Maksud saya adalah menggunakan hasil akhir biner dalam proses terpisah untuk menghasilkan raster yang menggambarkan penutup kanopi.

Saya menjalankan tes dengan empat shapefile dan menghasilkan raster 700MB dan membutuhkan waktu 35 menit (prosesor i5 & 8GB RAM). Melihat bahwa saya perlu menjalankan proses ini pada 3500 shapefile, saya akan sangat menghargai saran untuk merampingkan proses (lihat kode terlampir). Secara umum, apa cara terbaik untuk menangani data besar geoproses? Lebih khusus lagi, apakah ada perubahan pada kode atau alur kerja yang dapat membantu meningkatkan efisiensi?

Edit :

Waktu (% dari total) untuk tugas geoproses:

  • Gabung = 7,6%
  • Integrasi = 7,1%
  • Fitur untuk Lyr = 0
  • Buffer = 8,8%
  • Poli ke Raster = 74,8%
  • Reklasifikasi = 1,6%

masukkan deskripsi gambar di sini

# 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")
Harun
sumber
3
Mungkin perlu memasukkan beberapa kode waktu kinerja untuk menetapkan apakah sebagian besar waktu akan menjadi satu atau beberapa langkah - sehingga mereka dapat difokuskan untuk mencoba dan menemukan keuntungan kinerja
PolyGeo
5
Saya tidak berpikir Anda memiliki banyak opsi untuk meningkatkan kinerja jika Anda tetap menggunakan ArcPy. Mungkin Anda bisa melihat alat lain untuk melakukan ini? Alat seperti FME atau mungkin postgis?
tmske
3
Tidak jelas jenis piksel apa yang digunakan, tetapi jika itu adalah "Byte" (yang seharusnya), maka penyimpanan data mentah akan menjadi 5000x7000 = 35Mb (~ 33,4MB) per raster, yang sebenarnya tidak terlalu besar. Namun, dimensi berikutnya 3500 (dimensi waktu?) Meningkatkan ukuran mentah total menjadi ~ 114GB.
Mike T
5
Meskipun saya tidak dapat mengatakan dari deskripsi ini apa yang dilakukan algoritma (atau yang dimaksudkan untuk dilakukan), dalam banyak kasus buffer titik diikuti oleh rasterisasi harus diganti oleh rasterisasi titik diikuti oleh statistik fokus (biasanya rata-rata atau jumlah). Hasilnya akan sama tetapi, dengan menghindari langkah-langkah buffering panjang dan rasterisasi, itu akan diperoleh jauh lebih cepat. Saya (sangat) menduga speedup tambahan substansial dapat diperoleh tetapi tidak dapat memberikan saran khusus karena ketidakjelasan deskripsi prosedur.
whuber
2
Buffer di sekitar titik adalah ukuran variabel (berdasarkan nilai z titik). Saya-berpikir- untuk masih melakukan statistik fokus, Anda harus membagi poin hasil berdasarkan nilai z dan melakukan statistik raster dan fokus pada setiap set (menggunakan z sebagai jari-jari pada lingkungan melingkar dengan maksimum sebagai stat). Kemudian jalankan Statistik Sel di semua 9 raster dengan stat maksimum untuk menggabungkan hasilnya. (Yang mungkin masih jauh lebih cepat daripada buffer dan rasterize dengan set data besar.)
blord-castillo

Jawaban:

10

Beberapa perubahan algoritma yang seharusnya membantu Anda.

Jalankan pilihan Anda terlebih dahulu sebelum menggabungkan atau mengintegrasikan. Ini akan mengurangi secara signifikan pada fungsi-fungsi selanjutnya yang paling mahal.

Menggabungkan dan mengintegrasikan keduanya adalah memori yang mahal, jadi Anda ingin terus menghilangkan fitur saat Anda membawa kelas fitur, dan mencoba untuk melakukan penggabungan Anda dalam pohon biner untuk menjaga ukuran gabungan dan terintegrasi ke bawah. mis. untuk empat shapefile Anda menggabungkan dua shapefile dan mengintegrasikan; menggabungkan dua shapefile dan mengintegrasikan; menggabungkan dua kelas fitur yang dihasilkan dan mengintegrasikan.

Antrian pekerjaan Anda dimulai sebagai antrian referensi shapefile. Anda juga memiliki antrian hasil untuk menempatkan hasil. Metode run () untuk pekerja pemrosesan paralel Anda akan melakukan operasi ini: Ambil dua item dari antrian. Jika tidak ada item yang diambil (antrian kosong), hentikan pekerja. Jika satu item diambil, masukkan item itu langsung ke antrian hasil.

Jika dua item diambil, untuk setiap item: jika itu adalah shapefile, pilih untuk z <10 dan buat kelas fitur in_memory; selain itu, ini sudah merupakan kelas fitur in_memory dan melewatkan langkah pemilihan. Gabungkan dua kelas fitur in_memory untuk membuat kelas fitur in_memory baru. Hapus dua kelas fitur asli. Jalankan integrasi pada kelas fitur baru. Tempatkan kelas fitur itu ke dalam antrian hasil.

Kemudian jalankan loop sementara luar. Lingkaran dimulai dengan antrian shapefile dan menguji panjangnya lebih besar dari 1. Ia kemudian menjalankan antrian melalui pekerja. Jika antrian hasil memiliki panjang lebih besar dari 1, loop sementara mengeksekusi pemrosesan paralel lain yang dijalankan melalui pekerja hingga antrian hasil adalah 1 kelas fitur in_memory.

mis. Jika Anda mulai dengan 3.500 shapefile, antrian pertama Anda akan memiliki 3.500 pekerjaan. Kedua akan memiliki 1.750 pekerjaan. 875, 438, 219, 110, 55, 28, 14, 7, 4, 2, 1. Kemacetan besar Anda adalah ingatan. Jika Anda tidak memiliki cukup memori (dan Anda akan kehabisan memori dalam pembuatan antrian hasil pertama jika itu yang terjadi), maka modifikasi algoritme Anda untuk menggabungkan lebih dari 2 kelas fitur sekaligus mengintegrasikan, yang akan mengurangi ukuran antrian hasil pertama Anda dengan imbalan waktu pemrosesan lebih lama. Secara opsional, Anda dapat menulis file keluaran dan melompati menggunakan kelas fitur in_memory. Ini akan sangat memperlambat Anda, tetapi akan melewati hambatan memori.

Hanya setelah Anda melakukan penggabungan dan integrasi pada semua shapefile, diakhiri dengan satu kelas fitur tunggal, kemudian Anda melakukan buffer, poli ke raster, dan klasifikasi ulang. Dengan cara itu ketiga operasi dilakukan hanya sekali dan Anda menjaga geometri Anda sederhana.

tuan-castillo
sumber
+1 untuk menggunakan ruang kerja in_memory jika data Anda akan masuk ke dalam memori. Ini secara signifikan mempercepat operasi geoproses.
RyanDalton
Ini barang bagus. Saya pikir itu bisa lebih baik dengan diagram dan beberapa psuedocode (atau kode nyata!).
blah238
Ya, saya berharap saya punya waktu untuk berkomitmen pada kode. Saya perlu menulis script demo pemrosesan paralel baru.
blord-castillo
14

Hal pertama yang akan saya lakukan adalah memantau pemanfaatan sumber daya sistem Anda menggunakan sesuatu seperti Resource Monitor di Windows 7 atau perfmon di Vista / XP untuk mengetahui apakah Anda CPU -, memori - atau IO-terikat .

Jika Anda kehabisan memori atau terikat IO, ada kemungkinan sangat sedikit yang dapat Anda lakukan selain memutakhirkan perangkat keras, mengurangi ukuran masalahnya, atau mengubah pendekatan sepenuhnya.

Jika Anda menentukan bahwa Anda terikat dengan CPU, saya akan bereksperimen dengan multiprocessingmodul, atau salah satu dari banyak paket pemrosesan paralel berbasis Python lain yang tersedia, untuk melihat apakah Anda dapat menggunakan lebih banyak core CPU untuk mempercepat operasi Anda.

Trik untuk multiprosesor dan paralelisme secara umum adalah menemukan skema partisi yang baik yang:

  1. Memungkinkan Anda untuk membagi input menjadi set kerja yang lebih kecil, lalu menggabungkan kembali hasilnya dengan cara yang masuk akal,
  2. Menambahkan jumlah overhead terkecil (beberapa tidak dapat dihindari dibandingkan dengan pemrosesan serial), dan
  3. Memungkinkan Anda menyesuaikan ukuran set kerja agar memanfaatkan sumber daya sistem untuk kinerja yang optimal.

Anda dapat menggunakan skrip yang saya buat dalam jawaban ini sebagai titik awal: Kode Porting Avenue untuk Menghasilkan Bayangan Bangunan ke ArcPy / Python untuk ArcGIS Desktop?

Lihat juga posting blog ESRI Geoprocessing ini tentang subjek: Python Multiprocessing - Pendekatan dan Pertimbangan

Saya pikir bahwa kasus Anda akan menjadi lebih menantang karena sifat yang lebih "kotak hitam" dari alat yang Anda gunakan, daripada array geometri berbutir halus yang saya kerjakan. Mungkin bekerja dengan array NumPy mungkin berguna.

Saya juga menemukan beberapa bahan bacaan yang menarik jika Anda ingin melihat lebih jauh dari arcpy:

blah238
sumber