Упорядкування коду Python для великих даних


34

У мене є код Python, який призначений приймати точкові файли через наступний робочий процес:

  1. Злиття очок
  2. Інтегруйте точки, так що будь-які точки, що знаходяться на відстані 1 м одна від одної, стають однією точкою
  3. Створіть шар Feature, де вибираються точки з z <10
  4. Буферні очки
  5. Полігон до растрової дозволу 1 м
  6. Перекласифікуйте, де 1 - 9 = 1; NoData = 0

Кожен формуляр має приблизно 250 000 до 350 000 точок, що охоплюють ~ 5x7 км. Дані точок, які використовуються як входи, представляють місця дерева. Кожна точка (тобто дерево) має пов'язане значення "z", яке представляє радіус крони і використовується в буферному процесі. Моя мета - використовувати підсумковий бінарний вихід в окремому процесі для отримання растрового опису кришкою навісу.

Я провів тест з чотирма формами файлів, і він дав растр 700 Мб і зайняв 35 хвилин (процесор i5 та 8 ГБ оперативної пам’яті). Бачачи, що мені потрібно запустити цей процес на 3500 форм-файлах, я буду вдячний за будь-яку пораду щодо впорядкування процесу (див. Доданий код). Взагалі кажучи, який найкращий спосіб впоратися з обробкою великих даних? Більш конкретно, чи є зміни в коді чи робочому процесі, які можуть допомогти підвищити ефективність?

Редагувати :

Час (% від загальної кількості) для виконання завдань з геообробки:

  • Злиття = 7,6%
  • Інтеграція = 7,1%
  • Особливість для Lyr = 0
  • Буфер = 8,8%
  • Полі-растр = 74,8%
  • Перекласифікувати = 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")

3
Можливо, варто ввести якийсь код часу роботи, щоб встановити, чи йде основна частина часу на один чи кілька кроків - щоб на них можна було зосередити увагу, щоб спробувати знайти підвищення продуктивності
PolyGeo

5
Я не думаю, що у вас є багато варіантів для підвищення продуктивності, якщо ви продовжуєте використовувати ArcPy. Можливо, ви можете переглянути інші інструменти для цього? Такі засоби, як FME або, можливо, постгіс?
тмм

3
Незрозуміло, який тип пікселя використовується, але якщо це "байт" (яким він повинен бути), то зберігання необроблених даних було б 5000x7000 = 35 Мб (~ 33,4 МБ) на растр, що насправді не так вже й велико. Однак наступний вимір 3500 (часовий вимір?) Збільшує загальний розмір сировини до ~ 114 ГБ.
Майк Т

5
Хоча я не можу сказати з цього опису, що алгоритм робить (або мав намір робити), у більшості випадків буфери точок з подальшою растерізацією повинні бути замінені растерізацією точок з наступною фокусною статистикою (як правило, середньою чи сумою). Результат буде таким самим, але, уникаючи тривалих етапів буферизації та полірастеризації, він буде отриманий набагато швидше. Я (настійно) підозрюю, що можна отримати значні додаткові прискорення, але не можу дати конкретних порад через невизначеність опису процедури.
whuber

2
Буфери навколо точок мають різний розмір (виходячи зі значення z точки). Я думаю, щоб все-таки робити фокальну статистику, вам доведеться розділити результати результатів на значення z і робити растрові та фокусні статистичні дані на кожному наборі (використовуючи z як радіус у круговому мікрорайоні з максимумом як стат). Потім запустіть Cell Cell Statistics на всіх 9 растрах з максимальним stat, щоб об'єднати результати разом. (Що, мабуть, набагато швидше, ніж буфер і розширюється за допомогою великого набору даних.)
blord-castillo

Відповіді:


10

Деякі зміни алгоритму, які повинні вам допомогти.

Виконайте свій вибір спочатку перед об'єднанням або інтеграцією. Це суттєво скоротить подальші функції, які є найдорожчими.

Об'єднання та інтеграція - це і дорога пам'ять, тому ви хочете продовжувати усунення функцій під час введення класів функцій, а також намагаєтесь робити злиття у двійковому дереві, щоб зберегти розмір об'єднань та інтеграції вниз. наприклад, для чотирьох форм-файлів ви з’єднуєте два файли форми та інтегруєте їх; об'єднати ще два профілі та інтегрувати; об'єднати два результуючі класи функцій та інтегрувати.

Черга вашої роботи починається з черги посилань формфайлу. У вас також є черга результатів для розміщення результатів. Метод run () для вашого паралельного обробника працівника виконає такі операції: Знімайте два елементи з черги. Якщо жоден предмет не взято (черга порожня), усуньте працівника. Якщо взято один елемент, покладіть його прямо в чергу результатів.

Якщо для кожного елемента взяті два елементи: якщо це файл форми, виберіть для z <10 та створіть клас функцій in_memory; інакше, це вже клас властивостей пам’яті та пропускає крок вибору. Об’єднайте два класи функцій in_memory, щоб створити новий клас функцій in_memory. Видаліть початкові два класи функцій. Виконати інтеграцію в новому класі функцій. Розмістіть цей клас функції у черзі результатів.

Потім запустіть зовнішню петлю. Цикл починається з черги формфіле і перевіряє довжину більше 1. Потім він запускає чергу через робітників. Якщо черга результатів має довжину більше 1, цикл while виконує іншу паралельну обробку, що проходить через робітників, доки черга результатів не буде 1 класом функцій in_memory.

Наприклад, якщо ви почнете з 3500 форм-файлів, у вашій першій черзі буде 3500 завдань. Другий матиме 1750 робочих місць. 875, 438, 219, 110, 55, 28, 14, 7, 4, 2, 1. Вашим великим вузьким місцем буде пам'ять. Якщо у вас недостатньо пам’яті (і у вас вичерпається пам’ять у створенні першої черги результатів, якщо це так), то змініть свій алгоритм, щоб об’єднати більше двох класів функцій одразу, а потім інтегрувати, що скоротить розмір першої черги результатів в обмін на довший час обробки. Необов’язково, ви можете записувати вихідні файли та пропускати, використовуючи класи функцій in_memory. Це значно сповільнить вас, але пройде через вузьке місце пам’яті.

Лише після того, як ви виконали об'єднання та інтеграцію на всіх файлах форм, що закінчуються одним класом функцій, ви виконуватимете буфер, полі для растрування та перекласифікацію. Таким чином ці три операції виконуються лише один раз, і ви зберігаєте свою геометрію простою.


+1 за використання робочої області in_memory, якщо ваші дані вмістяться в пам'яті. Це значно прискорює операції з геообробки.
RyanDalton

Це хороший матеріал. Я думаю, що це може бути ще краще з діаграмою та деяким psuedocode (або реальним кодом!).
blah238

Так, хотілося б, щоб я мав час взяти на себе зобов’язання кодувати. Мені потрібно написати новий паралельний демо-скрипт.
blord-castillo

14

Перше, що я зробив би - це відстежувати використання ресурсів вашої системи, використовуючи щось на зразок Resource Monitor в Windows 7 або perfmon в Vista / XP, щоб зрозуміти, чи є ви процесором , пам'яттю або IO-пов'язаними .

Якщо ви пам'ять або пов'язані з IO, можливо, ви можете зробити те, що оновлювати обладнання, зменшити розмір проблеми або повністю змінити підхід.

Якщо ви визначите, що ви пов'язані з процесором, я б експериментував з multiprocessingмодулем або одним із багатьох інших пакетів паралельної обробки на основі Python , щоб побачити, чи можете ви використовувати більше ядер CPU для прискорення своїх операцій.

Хитрість багатопроцесорної роботи та паралелізму в цілому полягає в пошуку хорошої схеми розподілу, яка:

  1. Дозволяє розділити вхід на менші робочі набори, а потім рекомбінувати результати таким чином, що має сенс,
  2. Додає найменшу кількість накладних витрат (деякі неминучі порівняно з серійною обробкою) та
  3. Дозволяє регулювати розмір робочого набору, щоб найкраще використовувати ресурси системи для оптимальної роботи.

Ви можете використовувати сценарій, який я створив у цій відповіді, як вихідну точку: Перенесення коду авеню для створення будівельних тіней для ArcPy / Python для ArcGIS Desktop?

Дивіться також цю публікацію в блозі ESRI про географічну обробку на тему: Багатопроцесорна робота Python - підходи та міркування

Я думаю, що ваш випадок буде ще більш складним через більш "чорний ящик" характер інструментів, які ви використовуєте, а не більш дрібнозернисті геометричні масиви, з якими я працював. Можливо, робота з масивами NumPy може стати в нагоді.

Я також натрапив на цікавий матеріал для читання, якщо ви хочете подивитися за аркпією:

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.