2014-10-16 4 views
5

Я пытаюсь оптимизировать свой код с помощью модуля Python multiprocessing.Pool, но я не получаю результаты ускорения, которые я бы логически ожидал.Многопроцессорность Python не дает ожидаемого ускорения

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

import time 
import numpy as np 
import scipy.sparse as sp 

def calculate(vector, matrix = None): 
    for i in range(50): 
     v = matrix.dot(vector) 
    return v 

if __name__ == '__main__': 
    N = 1e6 
    matrix = sp.rand(N, N, density = 1e-5, format = 'csr') 
    t = time.time() 
    res = [] 
    for i in range(10): 
     res.append(calculate(np.random.rand(N), matrix = matrix))  
    print time.time() - t 

Способ заканчивается примерно 30 секунд.

Теперь, поскольку расчет каждого элемента results не зависит от результатов каких-либо других вычислений, естественно предположить, что вычисление паралелей ускорит процесс. Идея состоит в том, чтобы создать 4 процесса, и если каждый из них выполняет некоторые вычисления, то время, необходимое для завершения всех процессов, должно уменьшаться примерно на 4. Для этого я написал следующий код:

import time 
import numpy as np 
import scipy.sparse as sp 
from multiprocessing import Pool 
from functools import partial 

def calculate(vector, matrix = None): 
    for i in range(50): 
     v = matrix.dot(vector) 
    return v 

if __name__ == '__main__': 
    N = 1e6 
    matrix = sp.rand(N, N, density = 1e-5, format = 'csr') 

    t = time.time() 
    input = [] 
    for i in range(10): 
     input.append(np.random.rand(N)) 
    mp = partial(calculate, matrix = matrix) 
    p = Pool(4) 
    res = p.map(mp, input) 
    print time.time() - t 

Моя проблема заключается в том, что этот код занимает немного выше 20 секунд для запуска, так что я даже не повысить производительность за счет фактора 2! Хуже того, производительность не улучшается, даже если в пуле есть 8 процессов! Любая идея, почему ускорение не происходит?


Примечание: Мой фактический метод занимает гораздо больше времени, а входные векторы сохраняются в файле. Если я разделяю файл на 4 штук, а затем запускаю мой сценарий в отдельном процессе для каждого файла вручную, каждый процесс завершается в четыре раза быстрее, чем для всего файла (как и ожидалось). Я confuzed почему эта скорость вверх (что, очевидно, возможно) не происходит с multiprocessing.Pool


Эди: Я только что нашел Multiprocessing.Pool makes Numpy matrix multiplication slower этот вопрос, который может быть связан. Я должен проверить, хотя.

+0

Вопрос: Сколько физических (не гипертекстовых) ядер процессора использует ли система, на которой вы работаете? –

+0

@KlausD. Физически у меня есть «4» ядра. Вот почему я вручную разбил файл на '4', а не на' 8'. – 5xum

+0

Если вы поставили контрольные значения 'time.time()' в свой метод 'calculate', вы увидите, что 50 вызовов' dot' занимают почти 4 раза дольше, чем в непараллельном случае. Мне непонятно, почему, потому что такие инструменты, как 'top', делают его непараллельным, используют только один процессор полностью, тогда как параллельный случай делает его похожим на то, что 4 процессора полностью используются. –

ответ

0

Try:

p = Pool(4) 
for i in range(10): 
    input = np.random.rand(N) 
    p.apply_async(calculate, args=(input, matrix)) # perform function calculate as new process with arguments input and matrix 

p.close() 
p.join() # wait for all processes to complete 

Я подозреваю, что «частичный» объект и карта приводят к поведению блокировки. (Хотя я никогда не использовал частичные, так что я с ним не знаком.)

«apply_async» (или «map_async») являются многопроцессорных методы, которые конкретно не блокируют - (см: Python multiprocessing.Pool: when to use apply, apply_async or map?)

Вообще , для «смущающих параллельных проблем», подобных этому, apply_async работает для меня.

EDIT:

Я склонен записывать результаты в базы данных MySQL, когда я сделал - реализация я предоставил не работает, если это не ваш подход. «Карта», вероятно, является правильным ответом, если вы хотите использовать порядок в списке, как ваш способ отслеживания, какая запись есть, но я остаюсь подозрительной к «частичным» объектам.

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

  • Нет связанных вопросов^_^