Я пишу код, который должен вычислять большое количество проблем с собственными значениями (типичный размер матриц - несколько сотен). Мне было интересно, можно ли ускорить процесс с помощью модуля IPython.parallel
. Как бывший пользователь MATLAB и новичок в Python, я искал что-то похожее на MATLAB parfor
...
Следуя некоторым онлайн-учебникам, я написал простой код, чтобы проверить, ускоряет ли он вычисления вообще, и обнаружил, что это не так, и часто фактически замедляет их (зависит от случая). Я думаю, что, возможно, я что-то упустил, и, возможно, scipy.linalg.eig
реализован таким образом, что он использует все доступные ядра, и, пытаясь распараллелить его, я прерываю управление двигателем.
Вот "параллельный" код:
import numpy as np
from scipy.linalg import eig
from IPython import parallel
#create the matrices
matrix_size = 300
matrices = {}
for i in range(100):
matrices[i] = np.random.rand(matrix_size, matrix_size)
rc = parallel.Client()
lview = rc.load_balanced_view()
results = {}
#compute the eigenvalues
for i in range(len(matrices)):
asyncresult = lview.apply(eig, matrices[i], right=False)
results[i] = asyncresult
for i, asyncresult in results.iteritems():
results[i] = asyncresult.get()
Непараллельный вариант:
#no parallel
for i in range(len(matrices)):
results[i] = eig(matrices[i], right=False)
Разница во времени ЦП для этих двух очень тонкая. Если в дополнение к проблеме собственных значений распараллеленная функция должна выполнить еще несколько матричных операций, она начинает работать вечно, то есть как минимум в 5 раз дольше, чем нераспараллеленный вариант.
Прав ли я, что проблемы с собственными значениями не совсем подходят для такого распараллеливания, или я упускаю суть?
Большое спасибо!
ОТРЕДАКТИРОВАНО 29 июля 2013 г.; 12:20 по московскому времени
Следуя предложению moarningsun, я попытался запустить eig
, зафиксировав количество потоков с помощью mkl.set_num_threads
. Для матрицы 500 на 500 минимальное время набора 50 повторений следующее:
No of. threads minimum time(timeit) CPU usage(Task Manager)
=================================================================
1 0.4513775764796151 12-13%
2 0.36869288559927327 25-27%
3 0.34014644287680085 38-41%
4 0.3380558903450037 49-53%
5 0.33508234276183657 49-53%
6 0.3379019065051807 49-53%
7 0.33858615048501406 49-53%
8 0.34488405094054997 49-53%
9 0.33380300334101776 49-53%
10 0.3288481198342197 49-53%
11 0.3512653110685733 49-53%
Если не считать случая с одним потоком, существенной разницы нет (может быть, 50 сэмплов - это слишком мало...). Я все еще думаю, что упускаю суть, и многое можно было бы сделать для улучшения производительности, но не совсем уверен, как это сделать. Они были запущены на 4-ядерной машине с включенной гиперпоточностью, что дало 4 виртуальных ядра.
Спасибо за любой вклад!
scipy.linalg.eig
реализовано таким образом, что использует все доступные ядра, но проверяли ли вы это на самом деле? На моем двухъядерном ПКeig
использует процессор на 99%. - person   schedule 24.07.2013eig
обычно использует 50-52% доступной мощности процессора, когдаIPython.parallel
не используется. - person MKK_   schedule 24.07.2013IPython.parallel
enbaled загрузка ЦП подскакивает до 100%, но вычисления выполняются медленнее? Я имею в виду, действительно ли эти виртуальные ядра мешают вычислению eig, которое по своей сути выполняется на 4 ядрах безIPython.parallel
? Спасибо - person MKK_   schedule 25.07.2013eig
только для 1 потока и посмотреть, как он масштабируется с количеством движков IPython? Например, мой scipy использует подпрограммы LAPACK из MKL, поэтому я могу делатьimport mkl; mkl.set_num_threads(1)
. - person   schedule 29.07.2013scipy.linalg.eig
использует доступные ресурсы ЦП и можно ли это как-то улучшить, используя соответствующие инструменты, такие какIPython.parallel
... - person MKK_   schedule 29.07.2013