Я медленно переключаюсь на Python, и я хотел бы сделать простой тест для сравнения производительности простого суммирования массива. Я генерирую случайный массив 1000x1000 и добавляю по одному к каждому из значений в этом массиве.
Здесь мой скрипт в Python:
import time
import numpy
from numpy.random import random
def testAddOne(data):
"""
Test addOne
"""
return data + 1
i = 1000
data = random((i,i))
start = time.clock()
for x in xrange(1000):
testAddOne(data)
stop = time.clock()
print stop - start
И моя функция в MATLAB:
function test
%parameter declaration
c=rand(1000);
tic
for t = 1:1000
testAddOne(c);
end
fprintf('Structure: \n')
toc
end
function testAddOne(c)
c = c + 1;
end
Python занимает 2,77 - 2,79 секунды, то же, что и функция MATLAB (на самом деле меня очень впечатляет Numpy!). Что мне нужно изменить на мой скрипт Python для использования многопоточности? Я не могу в MATLAB, так как не надеваю, у меня есть панель инструментов.
Многопоточность в Python полезна только для ситуаций, когда потоки блокируются, например, при вводе данных, что здесь не так (см. Ответы на этот вопрос для более подробной информации). Тем не менее, многопроцессорная обработка проста в Python. Здесь рассматривается многопроцессорность.
Программа, использующая аналогичный подход к вашему примеру, ниже
import time
import numpy
from numpy.random import random
from multiprocessing import Process
def testAddOne(data):
return data + 1
def testAddN(data,N):
# print "testAddN", N
for x in xrange(N):
testAddOne(data)
if __name__ == '__main__':
matrix_size = 1000
num_adds = 10000
num_processes = 4
data = random((matrix_size,matrix_size))
start = time.clock()
if num_processes > 1:
processes = [Process(target=testAddN, args=(data,num_adds/num_processes))
for i in range(num_processes)]
for p in processes:
p.start()
for p in processes:
p.join()
else:
testAddN(data,num_adds)
stop = time.clock()
print "Elapsed", stop - start
Более полезным примером является использование пула рабочих процессов для последовательного добавления 1 в разные матрицы.
import time
import numpy
from numpy.random import random
from multiprocessing import Pool
def testAddOne(data):
return data + 1
def testAddN(dataN):
data,N=dataN
for x in xrange(N):
data = testAddOne(data)
return data
if __name__ == '__main__':
num_matrices = 4
matrix_size = 1000
num_adds_per_matrix = 2500
num_processes = 4
inputs = [(random((matrix_size,matrix_size)), num_adds_per_matrix)
for i in range(num_matrices)]
#print inputs # test using, e.g., matrix_size = 2
start = time.clock()
if num_processes > 1:
proc_pool = Pool(processes=num_processes)
outputs = proc_pool.map(testAddN, inputs)
else:
outputs = map(testAddN, inputs)
stop = time.clock()
#print outputs # test using, e.g., matrix_size = 2
print "Elapsed", stop - start
В этом случае код в testAddN
фактически что-то делает с результатом вызова testAddOne
. И вы можете раскомментировать заявления печати, чтобы проверить, что выполняется какая-то полезная работа.
В обоих случаях я изменил общее количество добавлений до 10000; с меньшим количеством добавлений стоимость запуска процессов становится более значимой (но вы можете экспериментировать с параметрами). И вы также можете экспериментировать с num_processes
. На моей машине я обнаружил, что по сравнению с запуском в том же процессе с num_processes=1
я получил чуть меньше 2x ускорения, num_processes=4
четыре процесса с num_processes=4
.
MATLAB
, добавлять по одному элементу за раз, когда вы можете сделать это за один раз, и потому что именно в этом заключается сила MATLAB? Если выinline
функцию, я не удивлюсь, если вы получите заметное улучшение с помощьюMATLAB
.t = 1:1000
может бытьt = 1:randi([1000,2000])