Максимизация использования процессора


9

Мой скрипт пересекает линии с полигонами. Это долгий процесс, поскольку в нем более 3000 линий и более 500000 полигонов. Я выполнил из PyScripter:

# Import
import arcpy
import time

# Set envvironment
arcpy.env.workspace = r"E:\DensityMaps\DensityMapsTest1.gdb"
arcpy.env.overwriteOutput = True

# Set timer
from datetime import datetime
startTime = datetime.now()

# Set local variables
inFeatures = [r"E:\DensityMaps\DensityMapsTest.gdb\Grid1km_Clip", "JanuaryLines2"]
outFeatures = "JanuaryLinesIntersect"
outType = "LINE"

# Make lines
arcpy.Intersect_analysis(inFeatures, outFeatures, "", "", outType)

#Print end time
print "Finished "+str(datetime.now() - startTime)


У меня вопрос: есть ли способ заставить процессор работать на 100%? Он работает на 25% все время. Я предполагаю, что скрипт будет работать быстрее, если процессор будет на 100%. Неправильное предположение?
Моя машина это:

  • Windows Server 2012 R2 Standard
  • Процессор: Intel Xeon CPU E5-2630 0 @ 2,30 ГГц 2,29 ГГц
  • Установленная память: 31,6 ГБ
  • Тип системы: 64-разрядная операционная система, 64-разрядный процессор


введите описание изображения здесь


Я настоятельно рекомендую перейти на многопоточность. Это нетривиально настроить, но более чем компенсирует усилия.
Alok JHA

1
Какой вид пространственного индекса вы применили к своим полигонам?
Кирк Куйкендалл

1
Кроме того, вы пробовали ту же операцию с ArcGIS Pro? Это 64 бит и поддерживает многопоточность. Я был бы удивлен, если он достаточно умен, чтобы разбить Intersect на несколько потоков, но стоит попробовать.
Кирк Кайкендалл

Класс объектов полигонов имеет пространственный индекс с именем FDO_Shape. Я не думал об этом. Должен ли я создать еще один? Разве этого недостаточно?
Мануэль Фриас

1
Так как у вас много оперативной памяти ... вы пытались скопировать полигоны в класс объектов в памяти, а затем пересекать линии с этим? Или, если держать его на диске, вы пытались сжать его? Предположительно, сжатие улучшает ввод / вывод.
Кирк Кайкендалл,

Ответы:


13

Позвольте мне угадать: ваш процессор имеет 4 ядра, поэтому 25% использования процессора, это 100% использование одного ядра и 3 незанятых ядра.

Поэтому единственное решение - сделать код многопоточным, но это не простая задача.


4
Процессор он упоминает использует 6 ядер и 12 потоков.
Керстен

5
Привет, я не могу понизить голос, но я бы хотел! К сожалению, в Python есть GIL, поэтому вы вообще не можете использовать многопоточность (лучшее, что вы можете сделать, это разблокировать GIL, когда поток блокирует системный вызов)
Alec Teal

2
@AlecTeal вы определенно можете, например, с помощью Jython или multiprocessingмодуля.
правостороннее

@elyse собирается "О, да, вы можете полностью сделать это на Python, если под Python вы подразумеваете Jython", это не считается. Мне нужно было бы рассмотреть многопроцессорность, сможет ли импорт переопределить то, что делает Python Python?
Алек Тил

@AlecTeal Это порождает процессы (которые являются одним из способов сделать параллелизм). Смотрите документацию к multiprocessingмодулю.
rightfold

13

Я не уверен, что это задача, связанная с процессором. Я думаю, что это будет операция ввода-вывода, поэтому я буду стремиться использовать самый быстрый диск, к которому у меня был доступ.

Если E: сетевой диск, то устранение этого будет первым шагом. Если это не высокопроизводительный диск (поиск <7 мс), то это будет второе. Вы можете получить некоторое преимущество от копирования слоя многоугольника в in_memoryрабочую область, но это может зависеть от размера класса объектов многоугольника и от того, используете ли вы 64-битную фоновую обработку.

Оптимизация пропускной способности ввода-вывода часто является ключом к производительности ГИС, поэтому я рекомендую вам уделять меньше внимания индикатору ЦП и больше внимания индикаторам сети и диска.


4

У меня были похожие проблемы с производительностью в отношении скриптов arcpy, главное узкое место - не процессор, а жесткий диск; если вы используете данные из сети, что является худшим сценарием, попробуйте перенести данные на SSD-диск, а затем запустить скрипт из командной строки. не из pyscripter, pyscripter немного медленнее, может быть, потому что он содержит некоторые вещи отладки, если вы не удовлетворены снова, подумайте о параллельном сценарии, потому что каждый поток питона занимает одно ядро ​​процессора, ваш процессор имеет 6 ядер, так что вы можете запустить 6 сценариев одновременно.


3

Поскольку вы используете python и, как предложено выше, рассмотрите возможность использования многопроцессорной обработки, если ваша проблема может выполняться параллельно.

Я написал небольшую статью на сайте Geonet о преобразовании скрипта Python в инструмент скрипта Python, который можно использовать в Model Builder. Документ перечисляет код и описывает некоторые подводные камни для запуска его в качестве инструмента-скрипта. Это только одно место, чтобы начать искать:

https://geonet.esri.com/docs/DOC-3824


Это похоже на путь! Ваш скрипт работает нормально, но я не знаю, как его изменить, чтобы он работал с моим скриптом. Лучше я думал о пересечении таблиц с полигонами и линиями. Есть идеи?
Мануэль Фриас

3

Как уже было сказано, вы должны использовать многопроцессорность или многопоточность . Но тут возникает предостережение: проблема должна быть делимой! Так что взгляните на https://en.wikipedia.org/wiki/Divide_and_conquer_algorithms .

Если ваша проблема делится, вы бы поступили так:

  • Создайте очередь, в которой вы храните входные данные для процессов / потоков
  • Создайте очередь, в которой результаты хранятся в
  • Создайте функцию или класс, который можно использовать как процесс / поток, который решает нашу проблему

Но, как сказал geogeek, это может быть не проблема ограничения процессора, а проблема ввода-вывода. Если у вас достаточно ОЗУ, вы можете предварительно загрузить все данные и затем обработать их, что дает преимущество в том, что данные могут быть прочитаны за один раз, что не всегда прерывает процесс расчета.


3

Я решил проверить это, используя 21513 линий и 498596 полигонов. Я протестировал многопроцессорный подход (12 процессоров на моей машине), используя этот скрипт:

import arcpy,os
import multiprocessing
import time
t0 = time.time()
arcpy.env.overwriteOutput = True
nProcessors=4
folder=r'd:\scratch'

def function(inputs):
        nGroup=inputs[0]
        pGons=inputs[1]
        lines=inputs[2]
        outFeatures = '%s%s%s_%i.shp' %(folder,os.sep,'inters',nGroup)
        fids= tuple([i for i in range(nGroup,500000,nProcessors-1)])
        lyr='layer%s'%nGroup
        query='"FID" in %s' %str(fids)
        arcpy.MakeFeatureLayer_management(pGons,lyr,query)
        arcpy.Intersect_analysis([lines,lyr], outFeatures)
        return outFeatures
if __name__ == "__main__":
        inPgons='%s%s%s' %(folder,os.sep,'parcels.shp')
        inLines='%s%s%s' %(folder,os.sep,'roads.shp')
        m,bList=0,[]
        for i in range(nProcessors):
                bList.append([i,inPgons,inLines])
        pool = multiprocessing.Pool(nProcessors-1)
        listik=pool.map(function, bList)
##      apply merge here
        print listik
        print ('%i seconds' %(time.time()-t0))

Результаты, секунды:

  • нормальный локальный жесткий диск - 191
  • сверхбыстрый местный двигатель - 220
  • сетевой диск - 252

Самое смешное, что использование инструмента геообработки mxd заняло всего 87 секунд. Возможно, что-то не так с моим подходом к пулу ...

Как можно видеть, я использовал довольно уродливый запрос FID в (0, 4, 8,12… 500000), чтобы сделать задачу делимой.

Возможно, что запрос, основанный на предварительно рассчитанном поле, например CFIELD = 0, значительно сократит время.

Я также обнаружил, что время, сообщаемое многопроцессорными инструментами, может сильно различаться


1
Да, вы используете список, который идет вместе с проблемами блокировки. Попробуйте multiprocessing.queue. Также постарайтесь не записывать материал в рабочие процессы, но создайте очередь вывода с данными, которые вы хотите записать, и позвольте этому сделать процесс записи.
Бенджамин

3

Я не знаком с PyScripter, но если он поддерживается CPython, то вы должны пойти на многопроцессорность, а не многопоточность, если сама проблема делится (как уже упоминали другие).

CPython имеет глобальную блокировку интерпретатора , которая отменяет любые преимущества, которые могут принести несколько потоков в вашем случае .

Конечно, в других контекстах потоки Python полезны, но не в тех случаях, когда вы ограничены процессором.


1

У меня вопрос: есть ли способ заставить процессор работать на 100%?

Поскольку ваш ЦП имеет несколько ядер, вы будете максимально использовать только ядро, на котором работает ваш процесс. В зависимости от того, как настроен ваш чип Xeon, он будет работать до 12 ядер (6 физических и 6 виртуальных с включенной гиперпоточностью). Даже 64-битная ArcGIS на самом деле не может воспользоваться этим - и это может привести к ограничению использования ЦП, когда ваш однопоточный процесс максимально использует ядро, на котором он работает. Вам нужно многопоточное приложение, чтобы распределить нагрузку по ядрам ИЛИ (намного проще) вы можете уменьшить количество ядер, которые ваш ЦП работает, чтобы увеличить пропускную способность.

Самый простой способ снять ограничение ЦП (и убедиться, что это действительно ограничение ЦП, а не ограничения дискового ввода-вывода) - это изменить настройки BIOS для вашего Xeon и установить для него одно массивное одно ядро. Увеличение производительности будет существенным. Просто помните, что это также значительно снижает способность к многозадачности вашего ПК, поэтому лучше всего, если у вас есть выделенный процессор для реализации этого. Это гораздо проще, чем пытаться выполнять многопоточность вашего кода - что большинство функций ArcGIS Desktop (как в 10.3.1) не поддерживают в любом случае.


Какие настройки вы должны искать, чтобы превратить ваш процессор в «одно массивное одноядерное»?
Алекс МакВитти

1
Точное меню будет зависеть от вашего BIOS и микропрограммы микросхемы, но обычно оно находится в меню BIOS Setup> Advanced> CPU Configuration. Вы захотите отключить гиперпоточность, а затем установить количество активируемых ядер. Обычно 0 - это 1, если вам нужно одно большое ядро. Хорошая идея записать настройки перед тем, как что-то изменить - звучит очевидно, но их легко пропустить, если что-то не получится.
kingmi
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.