многопроцессорность всегда хуже, чем один процесс, независимо от того, сколько - PullRequest
1 голос
/ 29 апреля 2020

Я играю с multiprocessing в Python 3, чтобы попытаться понять, как это работает и когда это полезно.

Я основываю свои примеры на этот вопрос , который действительно старый (2012).

Мой компьютер представляет собой Windows, 4 физических ядра, 8 логических ядер.

Первый: несегментированные данные

Сначала я пытаюсь грубо вычислить numpy.sin для миллиона значений. Миллион значений - это один фрагмент, не сегментированный.

import time
import numpy
from multiprocessing import Pool

# so that iPython works
__spec__ = "ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>)"

def numpy_sin(value):
    return numpy.sin(value)

a = numpy.arange(1000000)

if __name__ == '__main__':

    pool = Pool(processes = 8)

    start = time.time()
    result = numpy.sin(a)
    end = time.time()
    print('Singled threaded {}'.format(end - start))
    start = time.time()
    result = pool.map(numpy_sin, a)
    pool.close()
    pool.join()
    end = time.time()
    print('Multithreaded {}'.format(end - start))

И я понимаю, что независимо от количества процессов «multi_threading» всегда занимает примерно в 10 раз больше, чем «однопоточность» , В диспетчере задач я вижу, что не все процессоры работают с максимальной нагрузкой, а общее использование процессора составляет от 18% до 31%.

Так что я пробую что-то еще.

Второе: сегментированные данные

Я пытаюсь разделить исходный 1 миллион вычислений на 10 пакетов по 100 000 каждый.
Затем я снова пытаюсь выполнить 10 миллионов вычислений в 10 пакетах по 1 миллиону каждый.

import time
import numpy
from multiprocessing import Pool

# so that iPython works
__spec__ = "ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>)"

def numpy_sin(value):
    return numpy.sin(value)

p = 3
s = 1000000

a = [numpy.arange(s) for _ in range(10)]

if __name__ == '__main__':

    print('processes = {}'.format(p))
    print('size = {}'.format(s))

    start = time.time()
    result = numpy.sin(a)
    end = time.time()

    print('Singled threaded {}'.format(end - start))

    pool = Pool(processes = p)
    start = time.time()
    result = pool.map(numpy_sin, a)
    pool.close()
    pool.join()
    end = time.time()

    print('Multithreaded {}'.format(end - start))

Я запустил этот последний фрагмент кода для разных процессов p и различной длины списка s, 100000 и 1000000.

По крайней мере теперь диспетчер задач выдает максимальную нагрузку на ЦП при 100% загрузке.

Я получаю следующие результаты за прошедшее время (ОРАНЖЕВЫЙ: многопроцессный, СИНИЙ : single):

enter image description here

enter image description here

То есть multiprocessing никогда выигрывает за один процесс.

Почему ??

Ответы [ 2 ]

2 голосов
/ 29 апреля 2020

Numpy изменяет способ запуска родительского процесса, так что он работает только на одном ядре. Вы можете позвонить os.system("taskset -p 0xff %d" % os.getpid()) после импорта numpy, чтобы сбросить привязку ЦП к использованию всех ядер.

См. этот вопрос для получения более подробной информации

0 голосов
/ 29 апреля 2020

Компьютер действительно может делать только одну вещь одновременно. При многопоточности или многопроцессорности компьютер действительно быстро переключается только между задачами. С предоставленной проблемой компьютер мог либо выполнить вычисления 1 000 000 раз, либо разделить работу между парой «рабочих» и выполнить 100 000 для каждого из 10 «рабочих». вычисление чего-либо прямо, так как компьютеру нужно время, чтобы создать несколько процессов, но пока что-то ждет. Главный пример, который я слышал, для веб-скрепинга. Если программа запрашивает данные из списка веб-сайтов и ждет, пока каждый сервер отправит данные, прежде чем запрашивать данные у следующего, программе придется подождать пару секунд. Если вместо этого компьютер использовал многопроцессорную обработку / многопоточность, чтобы сначала запросить все сайты, а все одновременно ждать, то общее время выполнения будет намного короче.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...