Контекст
Я пытаюсь запустить 1000 симуляций, которые включают (1) повреждение дорожной сети и затем (2) измерение задержек движения из-за повреждения.Оба этапа (1) и (2) включают создание нескольких «карт».На шаге (1) я создаю 30 карт повреждений.На шаге (2) я измеряю задержку трафика для каждой из этих 30 карт повреждений.Затем функция возвращает среднюю задержку трафика по 30 картам повреждений и переходит к следующему моделированию.Псевдокод для установки выглядит следующим образом:
for i in range(0,1000): # for each simulation
create 30 damage maps using parallel python
measure the traffic delay of each damage map using parallel
python
compute the average traffic delay for simulation i
Поскольку карты независимы друг от друга, я использовал параллельный пакет python на каждом шаге.
Проблема - Сообщение об ошибке
Код дважды выдавал следующую ошибку во время 72-го моделирования (из 1000) и прекращал работу во время шага (1), который включает в себя повреждение мостов.
An error has occurred during the function execution
Traceback (most recent call last):
File "/Library/Python/2.7/site-packages/ppworker.py", line 90, in run
__result = __f(*__args)
File "<string>", line 4, in compute_damage
File "<string>", line 3, in damage_bridges
File "/Library/Python/2.7/site-packages/scipy/stats/__init__.py", line 345, in <module>
from .stats import *
File "/Library/Python/2.7/site-packages/scipy/stats/stats.py", line 171, in <module>
from . import distributions
File "/Library/Python/2.7/site-packages/scipy/stats/distributions.py", line 10, in <module>
from ._distn_infrastructure import (entropy, rv_discrete, rv_continuous,
File "/Library/Python/2.7/site-packages/scipy/stats/_distn_infrastructure.py", line 16, in <module>
from scipy.misc import doccer
File "/Library/Python/2.7/site-packages/scipy/misc/__init__.py", line 68, in <module>
from scipy.interpolate._pade import pade as _pade
File "/Library/Python/2.7/site-packages/scipy/interpolate/__init__.py", line 175, in <module>
from .interpolate import *
File "/Library/Python/2.7/site-packages/scipy/interpolate/interpolate.py", line 32, in <module>
from .interpnd import _ndim_coords_from_arrays
File "interpnd.pyx", line 1, in init scipy.interpolate.interpnd
File "/Library/Python/2.7/site-packages/scipy/spatial/__init__.py", line 95, in <module>
from .ckdtree import *
File "ckdtree.pyx", line 31, in init scipy.spatial.ckdtree
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/multiprocessing/__init__.py", line 123, in cpu_count
with os.popen(comm) as p:
OSError: [Errno 35] Resource temporarily unavailable
Системы и версии
Я использую Python 2.7 в виртуальной среде PyCharm с параллельным python (pp) 1.6.5.Мой компьютер работает под управлением Mac OS High Sierra 10.13.3 с памятью 8 ГБ 1867 МГц DDR3.
Попытки исправить
Я понял, что проблема в пакете с параллельным python или в том, как я использовалэто, но в противном случае затрудняюсь понять, как это исправить.Это замечено как ошибка на странице параллельного питона - там размещено wkerzendorf:
Q: Я получаю Socket Error / Memory Error при использовании заданий, использующих> os.системные вызовы
A: Исправление, которое я нашел, использует subprocess.Popen и вставляет> stdout, stderr в подпроцесс.PIPE.Вот пример: subprocess.Popen (['ls -> rtl'], stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell = True).Это> исправило ошибку для меня.
Однако я совершенно не был уверен, где сделать эту модификацию.
Я также читал, что проблема может быть с моейсистемные ограничения, в соответствии с этим Ghost in the Machines сообщение в блоге .Однако, когда я попытался перенастроить максимальное количество файлов и максимальное количество пользовательских процессов, я получил следующее сообщение в терминале:
Could not set resource limits: 1: Operation not permitted
Код с использованием параллельного Python
Код, с которым я работаюwith довольно сложен (для запуска требуется несколько входных файлов), поэтому, боюсь, я не могу привести здесь минимальный воспроизводимый пример.Вы можете скачать и запустить версию кода по этой ссылке .
Ниже я включил код для шага (1), в котором я использую параллельный питон для создания 30 карт повреждений.Число рабочих равно 4.
ppservers = () #starting a super cool parallelization
# Creates jobserver with automatically detected number of workers
job_server = pp.Server(ppservers=ppservers)
print "Starting pp with", job_server.get_ncpus(), "workers"
# set up jobs
jobs = []
for i in targets:
jobs.append(job_server.submit(compute_damage, (lnsas[i%len(lnsas)], napa_dict, targets[i], i%sets, U[i%sets][:] ), modules = ('random', 'math', ), depfuncs = (damage_bridges, )))
# get the results that have already run
bridge_array_new = []
bridge_array_internal = []
indices_array = []
bridge_array_hwy_num = []
for job in jobs:
(index, damaged_bridges_internal, damaged_bridges_new, num_damaged_bridges_road) = job()
bridge_array_internal.append(damaged_bridges_internal)
bridge_array_new.append(damaged_bridges_new)
indices_array.append(index)
bridge_array_hwy_num.append(num_damaged_bridges_road)
Дополнительные функции
Функция compute_damage выглядит следующим образом.
def compute_damage(scenario, master_dict, index, scenario_index, U):
'''goes from ground-motion intensity map to damage map '''
#figure out component damage for each ground-motion intensity map
damaged_bridges_internal, damaged_bridges_new, num_damaged_bridges = damage_bridges(scenario, master_dict, scenario_index, U) #e.g., [1, 89, 598] #num_bridges_out is highway bridges only
return index, damaged_bridges_internal, damaged_bridges_new, num_damaged_bridges
Функцияmage_bridges выглядит следующим образом.
def damage_bridges(scenario, master_dict, scenario_index, u):
'''This function damages bridges based on the ground shaking values (demand) and the structural capacity (capacity). It returns two lists (could be empty) with damaged bridges (same thing, just different bridge numbering'''
from scipy.stats import norm
damaged_bridges_new = []
damaged_bridges_internal = []
#first, highway bridges and overpasses
beta = 0.6 #you may want to change this by removing this line and making it a dictionary lookup value 3 lines below
i = 0 # counter for bridge index
for site in master_dict.keys(): #1-1889 in Matlab indices (start at 1)
lnSa = scenario[master_dict[site]['new_id'] - 1]
prob_at_least_ext = norm.cdf((1/float(beta)) * (lnSa - math.log(master_dict[site]['ext_lnSa'])), 0, 1) #want to do moderate damage state instead of extensive damage state as we did here, then just change the key name here (see master_dict description)
#U = random.uniform(0, 1)
if u[i] <= prob_at_least_ext:
damaged_bridges_new.append(master_dict[site]['new_id']) #1-1743
damaged_bridges_internal.append(site) #1-1889
i += 1 # increment bridge index
# GB ADDITION -- to use with master_dict = napa_dict, since napa_dict only has 40 bridges
num_damaged_bridges = sum([1 for i in damaged_bridges_new if i <= 1743])
return damaged_bridges_internal, damaged_bridges_new, num_damaged_bridges