python struct.ошибка: формат " i " требует -2147483648

Я готов сделать инженерную функцию, используя модуль многопроцессорной обработки (multiprocessing.Pool.starmap(). Однако он выдает следующее сообщение об ошибке. Я предполагаю, что это сообщение об ошибке о размер вклада (2147483647 = 2^31 - 1?), так как тот же код работал плавно для фракции(frac=0.05) входных кадров данных (train_scala, test, ts). Я конвертирую типы фреймов данных как можно меньше, однако он не становится лучше.

версия anaconda 4.3.30 и Python версия 3.6 (64 бит). И размер памяти системы составляет более 128GB с более чем 20 ядрами. Вы хотите предложить какой-либо указатель или решение для преодоления этой проблемы? Если эта проблема вызвана большими данными для многопроцессорного модуля, сколько меньших данных я должен использовать для использования многопроцессорного модуля на Python3?

код:

from multiprocessing import Pool, cpu_count
from itertools import repeat    
p = Pool(8)
is_train_seq = [True]*len(historyCutoffs)+[False]
config_zip = zip(historyCutoffs, repeat(train_scala), repeat(test), repeat(ts), ul_parts_path, repeat(members), is_train_seq)
p.starmap(multiprocess_FE, config_zip)

Сообщение Об Ошибке:

Traceback (most recent call last):
  File "main_1210_FE_scala_multiprocessing.py", line 705, in <module>
    print('----Pool starmap start----')
  File "/home/dmlab/ksedm1/anaconda3/envs/py36/lib/python3.6/multiprocessing/pool.py", line 274, in starmap
    return self._map_async(func, iterable, starmapstar, chunksize).get()
  File "/home/dmlab/ksedm1/anaconda3/envs/py36/lib/python3.6/multiprocessing/pool.py", line 644, in get
    raise self._value
  File "/home/dmlab/ksedm1/anaconda3/envs/py36/lib/python3.6/multiprocessing/pool.py", line 424, in _handle_tasks
    put(task)
  File "/home/dmlab/ksedm1/anaconda3/envs/py36/lib/python3.6/multiprocessing/connection.py", line 206, in send
    self._send_bytes(_ForkingPickler.dumps(obj))
  File "/home/dmlab/ksedm1/anaconda3/envs/py36/lib/python3.6/multiprocessing/connection.py", line 393, in _send_bytes
    header = struct.pack("!i", n)
struct.error: 'i' format requires -2147483648 <= number <= 2147483647

дополнительные инфос!--6-->
  • historyCutoffs-это список целых чисел
  • train_scala-это фрейм данных pandas (377MB)
  • тест-это фрейм данных pandas (15 МБ)
  • ts-это фрейм данных pandas (547MB)
  • ul_parts_path-это список каталогов (строка)
  • is_train_seq-это список булевых

дополнительный код: метод multiprocess_FE

def multiprocess_FE(historyCutoff, train_scala, test, ts, ul_part_path, members, is_train):
    train_dict = {}
    ts_dict = {}
    msno_dict = {}
    ul_dict = {}
    if is_train == True:
        train_dict[historyCutoff] = train_scala[train_scala.historyCutoff == historyCutoff]
    else:
        train_dict[historyCutoff] = test
    msno_dict[historyCutoff] = set(train_dict[historyCutoff].msno)
    print('length of msno is {:d} in cutoff {:d}'.format(len(msno_dict[historyCutoff]), historyCutoff))
    ts_dict[historyCutoff] = ts[(ts.transaction_date <= historyCutoff) & (ts.msno.isin(msno_dict[historyCutoff]))]
    print('length of transaction is {:d} in cutoff {:d}'.format(len(ts_dict[historyCutoff]), historyCutoff))    
    ul_part = pd.read_csv(gzip.open(ul_part_path, mode="rt"))  ##.sample(frac=0.01, replace=False)
    ul_dict[historyCutoff] = ul_part[ul_part.msno.isin(msno_dict[historyCutoff])]
    train_dict[historyCutoff] = enrich_by_features(historyCutoff, train_dict[historyCutoff], ts_dict[historyCutoff], ul_dict[historyCutoff], members, is_train)

1 ответов


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

вы произвели объект, который при мариновании больше, чем помещается в i struct formatter (четырехбайтовое целое число со знаком), которое нарушает допущения, сделанные кодом.

вы можете делегировать чтение ваших фреймов данных вместо этого дочерний процесс отправляет только метаданные, необходимые для загрузки фрейма данных. Их общий размер приближается к 1GB, слишком много данных для обмена по каналу между вашими процессами.

слово принципы программирования раздел:

лучше наследовать, чем рассол / unpickle

при использовании spawn или forkserver методы запуска многих типов из multiprocessing нужно быть picklable так, что дочерние процессы могут их использовать. однако обычно следует избегать отправки общих объектов другим процессам с помощью каналов или очередей. Вместо этого вы должны организовать программу так, чтобы процесс, которому нужен доступ к общему ресурсу, созданному в другом месте, мог наследовать его от процесса предка.

если вы не работаете в Windows и используете либо spawn или forkserver методы, вы можете загрузить свои фреймы данных как globals до начать свой подпроцессы, в этот момент дочерние процессы будут "наследовать"данные через обычные механизмы совместного использования страниц памяти при записи в ОС.