2010-08-03 4 views
7

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

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

file.close() 

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

Спасибо ...

EDIT: Для того, чтобы ответить на комментарий Уэйн ... Я приуроченные их как раз и в разных порядках и получила довольно много Идентичные результаты каждый раз, так что я сомневаюсь, что это другой процесс. Я положил

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

+1

Можете ли вы показать, как вы измерили время? Вы пытались поменять порядок, который вы взяли? Тот факт, что вы пишете на диск, усложняет вопрос о времени (что, если '[insert-process-here]' писал на диск с более высоким приоритетом во время теста numpys?) –

+0

Спасибо за все ответы! Все были информативными. Извините, у меня недостаточно репутации, чтобы проголосовать за них! – pr0crastin8r

ответ

9

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

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

В NumPy, это больше распространено, чтобы сделать что-то вроде этого:

A = NP.random.randint(10, 100, 100).reshape(10, 10) 
w = A[A % 2 == 0] 
NP.save("test_file.npy", w) 
+3

+1 для A [A% 2 == 0], который является типом строки, которую OP захочет использовать, за исключением 1000 вместо 2, конечно. – tom10

5

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

$ 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 
Смежные вопросы