Многопроцессорность Python и сериализация данных

Я запускаю сценарий на школьном компьютере, используя модуль multiprocessing. Я часто сериализую данные. Это можно резюмировать кодом ниже:

import multiprocessing as mp
import time, pickle

def simulation(j):
    data = []
    for k in range(10):
        data.append(k)
        time.sleep(1)
        file = open('data%d.pkl'%j, 'wb')
        pickle.dump(data, file)
        file.close()
if __name__ == '__main__':
    processes = []
    processes.append(mp.Process(target = simulation, args = (1,) ))
    processes.append(mp.Process(target = simulation, args = (2,) ))
    for process in processes:
        process.start()
    for process in processes:
        process.join()

Поэтому, когда я на самом деле запускаю свой код для многих других симуляций и того, что я представляю как более интенсивные разнообразные задачи, я получаю следующую ошибку: IOError: [Errno 5] Input/output error обычно предшествует file.open(...) или file.close().

Мои вопросы:

  • Как исправить эту ошибку в моем скрипте?
  • Что означает эта ошибка для новичка в Python? Ссылки приветствуются.

Еще несколько заметок о моей процедуре:

  • Вместо того, чтобы установить для атрибута многопроцессорности daemon значение True, я использую screen для запуска сценария, а затем отсоединяюсь. Это также позволяет мне отключаться, не беспокоясь об остановке моего сценария.
  • Это похоже на связанный вопрос о печати с использованием модуля subprocess. Как я уже сказал, я явно не использовал демона, поэтому не уверен, что это поможет.
  • Обычно это происходит после работы в течение дня и происходит в разных процессах в разное время.

person Charlie    schedule 19.09.2014    source источник
comment
По совету друга я использовал команду bash nohup вместо screen, чтобы уменьшить количество «слоев» между мной и ядром. Грубо говоря, он сказал, что это может увеличить шансы того, что эта ошибка не возникнет. Впрочем, до сих пор...   -  person Charlie    schedule 03.10.2014


Ответы (1)


Ваша программа выглядит неплохо. В данном случае IOError просто означает "произошло что-то плохое". Весь набор смоделированных данных стал слишком большим для процесса Python, поэтому он завершился с таинственным сообщением.

Пара улучшений в следующей версии:

  • После создания некоторых данных добавьте их в файл данных, а затем извлеките их из памяти. Программа должна иметь примерно одинаковое использование ОЗУ с течением времени, а не использовать все больше и больше, а затем давать сбой.

  • Удобно, если файл представляет собой конкатенацию pickle объектов, мы можем легко распечатать каждый из них позже для дальнейшего изучения. Показан пример кода.

Повеселись!

источник

import multiprocessing as mp
import glob, time, pickle, sys

def simulation(j):
    for k in range(10):
        datum = {'result': k}
        time.sleep(1)
        with open('data%d.pkl'%j, 'ab') as dataf:
            pickle.dump(datum, dataf)

def show():
    for datname in glob.glob('data*.pkl'):
        try:
            print '*'*8, datname
            with open(datname, 'rb') as datf:
                while True:
                    print pickle.load(datf)
        except EOFError:
            pass

def do_sim():
    processes = []
    processes.append(mp.Process(target = simulation, args = (1,) ))
    processes.append(mp.Process(target = simulation, args = (2,) ))
    for process in processes:
        process.start()
    for process in processes:
        process.join()

if __name__ == '__main__':
    if '--show' in sys.argv:
        show()
    else:
        do_sim()

вывод "python ./msim.py --show"

******** data2.pkl
{'result': 0}
{'result': 1}
{'result': 2}
{'result': 3}
{'result': 4}
{'result': 5}
{'result': 6}
{'result': 7}
{'result': 8}
{'result': 9}
******** data1.pkl
{'result': 0}
{'result': 1}
{'result': 2}
{'result': 3}
{'result': 4}
{'result': 5}
{'result': 6}
{'result': 7}
{'result': 8}
{'result': 9}
person johntellsall    schedule 04.10.2014
comment
СПАСИБО БОЛЬШОЕ-ОЧЕНЬ БОЛЬШОЕ за ответ! Подозревал какие-то проблемы с памятью. Все еще не могу отследить это, но я проверю это снова. Я везде использую реализации numpy, подобные Matlab, поэтому у меня много кода, в котором я инициализирую большой массив (~ 10 ^ 3), сохраняю данные в отдельных записях массива и, наконец, выгружаю массив с помощью pickle после каждой итерации. Используйте словарь для хранения различных массивов по имени. Не знаю, смогу ли я изменить весь свой код без серьезных затрат времени. Любые другие забавные обходные пути приветствуются, но опять же, я так рад, что вы ответили. - person Charlie; 06.10.2014