Сумма массива Python против MATLAB

1

Я медленно переключаюсь на 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, так как не надеваю, у меня есть панель инструментов.

  • 0
    Действительно ли это справедливо для MATLAB , добавлять по одному элементу за раз, когда вы можете сделать это за один раз, и потому что именно в этом заключается сила MATLAB? Если вы inline функцию, я не удивлюсь, если вы получите заметное улучшение с помощью MATLAB .
  • 1
    @Divakar Вы должны проверить код еще раз, MATLAB добавляет их в один вызов. Что, вероятно, вводит вас в заблуждение, так это то, что я запускаю это 1000 раз, что также соответствует длине массива. Чтобы понять, цикл for t = 1:1000 может быть t = 1:randi([1000,2000])
Показать ещё 4 комментария
Теги:
arrays
numpy
multithreading

1 ответ

2
Лучший ответ

Многопоточность в 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.

  • 1
    Я пытаюсь ваш первый пример прямо сейчас, и я получил ускорение в 2,16 раза (с 4 процессами)
  • 0
    Все еще пытаюсь понять, что вы делаете во втором примере! Но спасибо за оба решения!
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню