2016-10-24 5 views
1

Я запускаю программу, которая сначала загружает 20 ГБ данных в память. Затем я буду выполнять N (> 1000) независимых задач, в которых каждый из них может использовать (только для чтения) часть данных 20 ГБ. Теперь я пытаюсь выполнить эти задачи с помощью многопроцессорности. Однако, как сообщает this answer, все глобальные переменные копируются для каждого процесса. В моем случае у меня недостаточно памяти для выполнения более 4 задач, так как моя память составляет всего 96 ГБ. Интересно, есть ли какое-либо решение этой проблемы, чтобы я мог полностью использовать все свои ядра, не потребляя слишком много памяти.многопроцессорное копирование глобальной переменной памяти

+0

Почему вы загружаете столько данных в память? Что вы делаете с данными? В идеале вы хотите загружать данные в мельчайшие возможные куски. – sytech

+0

@sytech Это характер моей задачи. Я думал о загрузке только данных, необходимых в каждом процессе, но это приведет к загрузке одних и тех же данных несколько раз. – wh408

+1

Таким образом, каждый процесс должен обрабатывать все данные, но делает ли он свою собственную вещь, а не возможность дублирования усилий? В этом случае вы можете попробовать поделиться данными в 'Manager.dict()' [здесь] (https://docs.python.org/2/library/multiprocessing.html#managers) или 'Manager.list () 'и порождаем несколько« Процессов ». Если все они выполняют одну и ту же задачу, вы можете обрезать данные и передать каждому процессу свой собственный кусок. Я не думаю, что вы можете принести больше процессов, чем ядра, и, похоже, вам нужны процессы '1000. – roganjosh

ответ

3

В linux разветвленные процессы имеют представление на родительском адресном пространстве с копией на запись. forking имеет легкий вес, и одна и та же программа работает как у родителя, так и у ребенка, за исключением того, что ребенок принимает другой путь выполнения. В качестве небольшого exmample,

import os 
var = "unchanged" 
pid = os.fork() 
if pid: 
    print('parent:', os.getpid(), var) 
    os.waitpid(pid, 0) 
else: 
    print('child:', os.getpid(), var) 
    var = "changed" 

# show parent and child views 
print(os.getpid(), var) 

Результаты в

parent: 22642 unchanged 
child: 22643 unchanged 
22643 changed 
22642 unchanged 

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

import multiprocessing as mp 
import os 

my_big_data = "well, bigger than this" 

def worker(index): 
    """get char in big data""" 
    return my_big_data[index] 

if __name__ == "__main__": 
    pool = mp.Pool(os.cpu_count()) 
    for c in pool.imap_unordered(worker, range(len(my_big_data)), chunksize=1): 
     print(c) 

В Windows нет модели fork-and-exec для запуска программ. Он должен запустить новый экземпляр интерпретатора python и клонировать все соответствующие данные для ребенка. Это тяжелый подъем!

+0

Aha. Хорошо, ключ к пониманию того, что происходит, это копирование на запись; несколько вещей кажутся противоречивыми при чтении о 'mp', если у вас нет более глубокого понимания. Спасибо за это объяснение, upvote. Из любопытства я все еще вынужден использовать «Менеджеров» из-за Windows; в моем случае, это создало бы еще один 20-гигабайтный объект (так оригинал + 'Manager' = 40 ГБ), чтобы инициализировать общий ресурс? Документы предполагают, что процессы получают доступ к общему списку/dict через прокси-сервер к _Manager_, но я никогда не работал с достаточно большими данными в 'mp' для тестирования. – roganjosh

+0

спасибо @tdelaney, это зависит от версий python (2.7 для моего случая) и способа реализации (pool.map, imap, imap_unordered)? – wh408

+1

@whan - 'map' и' imap' оба ждут завершения всей обработки и возвращают результаты в том порядке, в котором они были отправлены. Если вам не нужен порядок возврата, 'imap_unordered' является более эффективным и будет использовать меньше памяти, если результаты будут большими. Многопроцессорность очень похожа на python 2.x и 3.x. 'map' и' imap_unordered' являются хорошими вариантами в зависимости от того, хотите ли вы упорядоченные результаты. – tdelaney

Смежные вопросы