2015-10-29 6 views
3

Я пытаюсь преобразовать одну из моих программ, чтобы использовать многопроцессорную обработку, предпочтительно многопроцессорные пулы, поскольку они кажутся более простыми. На высоком уровне процесс создает массив патчей из изображений, а затем передает их на GPU для обнаружения объекта. Процессор и часть GPU занимают около 4 с каждый, однако процессор имеет 8 ядер, и ему не нужно ждать GPU, потому что после передачи GPU дальнейшие операции с данными не выполняются.Хороший пример реализации многопроцессорности?

Вот схема того, как я полагаю, что это должно работать: multiprocess diagram

Чтобы помочь процессу я хотел бы демонстрацию с высокой версией уровня моей реализации. Скажем, мы перебираем список изображений в папке с 10 изображениями. Мы изменяем размер изображения 4 за раз. Затем мы преобразуем их в черно-белые два за раз, мы можем принять преобразование в качестве части GPU процесса здесь. Вот то, что код будет выглядеть следующим образом:

def im_resize(im, num1, num2): 
    return im.resize((num1, num2), Image.ANTIALIAS) 

def convert_bw(im): 
    return im.convert('L') 

def read_images(path): 
    imlist = [] 
    for pathAndFileName in glob.iglob(os.path.join(path, "*")): 
     if pathAndFileName.endswith(tuple([".jpg", ".JPG"])): 
      imlist.append(Image.open(pathAndFileName)) 
    return imlist 


img_list = read_images("path/to/images/") 
final_img_list = [] 

for image in img_list: 

    # Resize needs to run concurrently on 4 processes so that the next img_tmp is always ready to go for convert 
    img_tmp = im_resize(image, 100, 100) 

    # Convert is limited, need to run on 2 processes 
    img_tmp = convert_bw(img_tmp) 
    final_img_list.append(img_tmp) 

Причину для определенного числа процессов и такое из-за показатели производительности системы, это то, что позволит сократить время выполнения. Я просто хочу удостовериться, что GPU не должен ждать, пока процессор завершит обработку изображений, и я хочу, чтобы постоянная очередь была заполнена предварительно обработанными изображениями, готовыми для запуска графического процессора. Я бы предпочел бы сохранить максимальный размер в очереди около 4-10 предварительно обработанных изображений. Если вы, ребята, можете помочь мне проиллюстрировать, как я мог бы добиться этого с помощью этого упрощенного примера, я уверен, что смогу понять, как его перевести в то, что мне нужно.

Спасибо!

+0

Там много примеров там. Вы просмотрели страницу [doc] (https://docs.python.org/2/library/multiprocessing.html)? Он иллюстрирует несколько сценариев. Вы в основном хотите отдельный пул для каждого этапа, на котором вы хотите заниматься фермой, используя ограниченное количество рабочих. Подумайте о том, какое функциональное преобразование вы применили бы к входному набору данных, чтобы получить выходную коллекцию, а затем вместо того, чтобы применять его с помощью 'map', примените его с помощью' Pool.map'. Затем вы используете 'get' или' join', чтобы отправить данные обратно в основной процесс как можно позже. –

+0

Я посмотрел на них, но поскольку python все последователен, я чувствую, что они не полностью иллюстрируют, как работают процессы, и как именно .join() контролирует их выполнение. Мне кажется, что .join просто полностью прекращает выполнение. Эта информация хороша для простого процесса, который должен разделить одну функцию на 4 процесса, но моя проблема потребует, чтобы один пул процессов постоянно работал в фоновом режиме, а другой пул из 2 ожидал предварительно обработанных данных. – alfredox

ответ

2

Вот предварительная попытка реализации того, что вы хотите:

... 

# Mapping functions can only take one arg, we provide tuple 
def img_resize_splat(a): 
    img_resize(*a) 

if __name__=="__main__": 
    # Make a CPU pool and a GPU pool 
    cpu = Pool(4) 
    gpu = Pool(2) 

    # Hopefully this returns an iterable, and not a list with all images read into memory 
    img_list = read_images("path/to/images/") 

    # I'm assuming you want images to be processed as soon as ready, order doesn't matter 
    resized = cpu.imap_unordered(img_resize_splat, ((img, 100, 100) for img in img_list)) 
    converted = gpu.imap_unordered(convert_bw, resized) 

    # This is an iterable with your results, slurp them up one at a time 
    for bw_img in converted: 
     # do something 
+0

Мне нравится ваш пример, но у меня есть некоторые вопросы. Список изображений может быть не меньше 1000, но до 100 000, поэтому я хотел бы ограничить размер очереди. Я хотел бы, чтобы 4 одновременных процесса выполняли заполнение очереди с максимальным размером 10 и продолжали заполнять его, когда изображения удаляются из очереди с помощью GPU 2 за раз. Заказ не имеет значения, но не похоже, что очередь контролируется в процессоре..imap_unordered()? – alfredox

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