Многопроцессорная обработка Python медленнее, чем одиночная - PullRequest
0 голосов
/ 04 мая 2018

Sort.py

import random
import time

def time_analysis(func):
    def do_func(*args, **kwargs):
        print('[INFO] \'{}\' analysis started (N={}).'.format(func.__name__, len(args[0])))
        start_time = time.clock()
        result = func(*args, **kwargs)
        end_time = time.clock()
        total_time = end_time - start_time
        print('[INFO] \'{}\' took {} seconds (N={}).'.format(func.__name__, total_time, len(args[0])))
        return result

    return do_func


@time_analysis
def bubble_sort(num_list):
    num_len = len(num_list)
    for i in range(num_len - 1):
        for j in range(num_len - i - 1):
            if num_list[j] > num_list[j + 1]:
                num_list[j], num_list[j + 1] = num_list[j + 1], num_list[j]
    return num_list

if __name__ == '__main__':
    N = 30000
    random_list = list(range(N))
    random.shuffle(random_list)
    bubble_sort(random_list)

    random_list = list(range(N))
    random.shuffle(random_list)
    bubble_sort(random_list)

Parallel.py

from multiprocessing import Pool, cpu_count
from Sort import *

def bubble_sort_parallel(*args, **kwargs):
    return bubble_sort(*args, **kwargs)

if __name__ == '__main__':
    N = 30000
    random_list = list(range(N))
    random.shuffle(random_list)
    pool.apply_async(bubble_sort_parallel, (random_list,))
    random_list = list(range(N))
    random.shuffle(random_list)
    pool.apply_async(bubble_sort_parallel, (random_list,))

    pool.close()
    pool.join()

Один поток занял всего 2 секунды, но многопроцессорная обработка заняла 8 секунд.

N = 300 000. Один поток занимал всего 200 секунд, а многопроцессорная обработка - 1400 секунд.

Почему многопроцессорная обработка медленнее, чем однопоточная?

Как мне улучшить производительность?

Платформа: Linux, pypy2.7-5.10.0, 4 ядра на моем компьютере

Multiprocessing: [Рисунок многопроцессорной обработки] [https://i.stack.imgur.com/QksXf.png]

Одна нить: [Фигура из одной нити] [https://i.stack.imgur.com/9HYw7.png]

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Надеюсь, вам многое уже было понятно: Pool.apply_async позволяет передавать работу другим процессам в пуле; он не распараллеливает автоматически одну функцию. Другими словами, обе версии выполняют каждую сортировку в одном потоке на одном ядре. Параллельная версия должна отправлять вызовы двух сортировок двум ядрам, но вы измеряете время выполнения каждого вида, а не выполнение всей программы, поэтому вы не обнаружите никакой экономии за счет перекрытия двух вызовов сортировки. (Кроме того, в настоящее время ваш код не включает создание объекта пула, поэтому я просто предполагаю , что вы использовали processes=N для N > 2 - хотя, опять же , это не имеет значения, поскольку вы измеряете не общее время выполнения, а время выполнения каждого вида.)

(Если нет, см. https://docs.python.org/2/library/multiprocessing.html#using-a-pool-of-workers а также https://docs.python.org/2/library/multiprocessing.html#module-multiprocessing.pool)

Это, однако, не объясняет, почему простая передача работы другому процессу приводит к более медленному времени выполнения. (Стоит отметить, что на моем MacBook Pro нет разницы во времени выполнения между простой версией и «параллельной» версией.) Причина медлительности - связь между процессами. Вы просите передать большой список через свой канал IPC, и это, очевидно, неэффективно. Вы можете продемонстрировать это сами: переместите создание и перетасовку списка в bubble_sort_parallel и укажите аргумент для поставляемой функции в pool.apply_async пустом списке. На моем компьютере это делает среду выполнения идентичной базовой версии.

0 голосов
/ 04 мая 2018

Я пробовал с N=15000. На моем компьютере это работало практически одинаково, то есть непараллельная версия сортировала один массив за 26 секунд. и параллельная версия отсортировала два массива за 28 сек. Я установил pool = Pool(2). Вы пытались увеличить N, возможно, ваши результаты будут сопоставимы для больших значений N в вашей среде.

p.s. Вам также следует помнить, что процессы порождения также требуют ресурсов, и в них задействованы некоторые инструменты синхронизации.

...