Как я могу максимизировать эффективность с массивами NumPy? - PullRequest
7 голосов
/ 03 августа 2010

Я только знакомлюсь с numpy, и я впечатлен его заявлениями о C-подобной эффективности с доступом к памяти в своих ndarrays. Я хотел увидеть различия между этими и питонными списками для себя, поэтому я провел быстрый тест времени, выполнив несколько таких же простых задач с NumPy без него. Numpy превзошел регулярные списки на порядок величины в распределении и арифметических операциях над массивами, как и ожидалось. Но этот сегмент кода, идентичный в обоих тестах, занимал около 1/8 секунды с обычным списком и чуть более 2,5 секунд с numpy:

file = open('timing.log','w')
for num in a2:
    if num % 1000 == 0:
        file.write("Multiple of 1000!\r\n")

file.close()

Кто-нибудь знает, почему это может быть, и если есть какой-то другой синтаксис, который я должен использовать для подобных операций, чтобы лучше использовать возможности ndarray?

Спасибо ...

РЕДАКТИРОВАТЬ: Чтобы ответить на комментарий Уэйна ... Я рассчитывал их оба раза и в разных порядках и каждый раз получал почти одинаковые результаты, поэтому я сомневаюсь, что это другой процесс. Я помещаю

start = time()
в верхнюю часть файла после простого импорта, а затем я получаю такие выражения, как
print 'Time after traversal:\t',(time() - start)
.

Ответы [ 3 ]

10 голосов
/ 03 августа 2010

a2 это массив NumPy, верно?Одна из возможных причин, по которой это может занять так много времени в NumPy (если активность других процессов не учитывает это, как предположил Уэйн Вернер), заключается в том, что вы выполняете итерацию по массиву с помощью цикла Python.На каждом шаге итерации Python должен извлечь одно значение из массива NumPy и преобразовать его в целое число Python, что не является особенно быстрой операцией.

NumPy работает намного лучше, когда вы можетевыполнять операции над всем массивом как единым целым.В вашем случае, один вариант (может быть, даже не самый быстрый) будет

file.write("Multiple of 1000!\r\n" * (a2 % 1000 == 0).sum())

Попробуйте сравнить это с эквивалентом чистого Python,

file.write("Multiple of 1000!\r\n" * sum(filter(lambda i: i % 1000 == 0, a2)))

или

file.write("Multiple of 1000!\r\n" * sum(1 for i in a2 if i % 1000 == 0))
6 голосов
/ 03 августа 2010

Меня не удивляет, что NumPy плохо работает со встроенными модулями Python при использовании вашего сниппета.Большая часть выигрыша в производительности в NumPy возникает из-за исключения циклов и доступа к массиву путем индексации:

В NumPy более распространено сделать что-то подобное:

5 голосов
/ 03 августа 2010

Доступ к элементам очень медленный для массивов. Используйте векторные операции:

$ python -mtimeit -s 'import numpy as np; a2=np.arange(10**6)' '
>    sum(1 for i in a2 if i % 1000 == 0)'
10 loops, best of 3: 1.53 sec per loop

$ python -mtimeit -s 'import numpy as np; a2=np.arange(10**6)' '
>    (a2 % 1000 == 0).sum()'
10 loops, best of 3: 22.6 msec per loop

$ python -mtimeit -s 'import numpy as np; a2=    range(10**6)' '
>    sum(1 for i in a2 if i % 1000 == 0)'
10 loops, best of 3: 90.9 msec per loop
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...