2012-06-06 3 views
30

Каковы различия в производительности и поведении между использованием функции sum на Python иNumPy? sum работает с массивами NumPy и numpy.sum работает над списками Python, и оба они возвращают одинаковый эффективный результат (не проверяли граничные случаи, такие как переполнение), но разные типы.Сумма Python по сравнению с numpy.sum NumPy

>>> import numpy as np 
>>> np_a = np.array(range(5)) 
>>> np_a 
array([0, 1, 2, 3, 4]) 
>>> type(np_a) 
<class 'numpy.ndarray') 

>>> py_a = list(range(5)) 
>>> py_a 
[0, 1, 2, 3, 4] 
>>> type(py_a) 
<class 'list'> 

# The numerical answer (10) is the same for the following sums: 
>>> type(np.sum(np_a)) 
<class 'numpy.int32'> 
>>> type(sum(np_a)) 
<class 'numpy.int32'> 
>>> type(np.sum(py_a)) 
<class 'numpy.int32'> 
>>> type(sum(py_a)) 
<class 'int'> 

Edit: Я думаю, что мой практический вопрос здесь бы использовать numpy.sum в списке целых чисел Python будет быстрее, чем с помощью Python собственного sum?

Кроме того, каковы последствия (включая производительность) использования целого числа Python по сравнению со скаляром numpy.int32? Например, для a += 1 существует ли поведение или разница в производительности, если тип a является целым числом Python или numpy.int32? Мне любопытно, если быстрее использовать скалярный тип NumPy типа numpy.int32 для значения, которое добавляется или вычитается из кода Python.

Для уточнения, я работаю над симуляцией биоинформатики, которая частично состоит из коллапсирующего многомерного numpy.ndarray s в единичные скалярные суммы, которые затем дополнительно обрабатываются. Я использую Python 3.2 и NumPy 1.6.

Заранее благодарен!

ответ

42

Мне было любопытно и приурочено. numpy.sum кажется намного быстрее для массивов numpy, но намного медленнее в списках.

import numpy as np 
import timeit 

x = range(1000) 
# or 
#x = np.random.standard_normal(1000) 

def pure_sum(): 
    return sum(x) 

def numpy_sum(): 
    return np.sum(x) 

n = 10000 

t1 = timeit.timeit(pure_sum, number = n) 
print 'Pure Python Sum:', t1 
t2 = timeit.timeit(numpy_sum, number = n) 
print 'Numpy Sum:', t2 

Результат при x = range(1000):

Pure Python Sum: 0.445913167735 
Numpy Sum: 8.54926219673 

Результат при x = np.random.standard_normal(1000):

Pure Python Sum: 12.1442425643 
Numpy Sum: 0.303303771848 

Я использую Python 2.7.2 и 1.6.1 Numpy

+0

+1, Но разве у вас нет этих результатов назад? – dawg

+0

@drewk, Да, я сделал их назад. Спасибо, что указали это! Исправлена. – Akavall

+0

Вы правы, когда 'np.sum' работает быстрее при использовании' np.array'. Но если вы время «np.sum (объект np.array)» и «sum (объект списка)», обе выполняют почти одинаково. – xyres

5

Нумерация должна быть намного быстрее, особенно если ваши данные уже являются массивными числами.

Многочисленные массивы представляют собой тонкий слой над стандартным массивом C. Когда numpy sum итерации над этим, он не делает проверку типов, и это очень быстро. Скорость должна быть сопоставима с выполнением операции с использованием стандарта C.

Для сравнения, используя сумму python, она должна сначала преобразовать массив numpy в массив python, а затем перебрать этот массив. Он должен выполнять некоторую проверку типов и, как правило, будет медленнее.

Точная сумма, которую сумма python меньше, чем сумма numpy, не определена, поскольку сумма python будет несколько оптимизированной функцией по сравнению с написанием вашей собственной функции sum в python.

+5

Он не преобразует массив numpy - массив numpy уже итерабельен в Python. С другой стороны, 'numpy.sum', возможно, придется преобразовать список в массив numpy, что объясняет результаты синхронизации @ Akavall. –

+1

Независимо от того, выполняется ли преобразование в виде массива в массив или путем персонализации отдельных элементов, вы на каком-то уровне должны преобразовывать элемент (от/к родным типам), и именно это я пытался сделать. – Claris

3

Заметьте, что сумма Python на многомерные массивы numpy будут выполнять только сумму по первой оси:

sum(np.array([[[2,3,4],[4,5,6]],[[7,8,9],[10,11,12]]])) 
Out[47]: 
array([[ 9, 11, 13], 
     [14, 16, 18]]) 

np.sum(np.array([[[2,3,4],[4,5,6]],[[7,8,9],[10,11,12]]]), axis=0) 
Out[48]: 
array([[ 9, 11, 13], 
     [14, 16, 18]]) 

np.sum(np.array([[[2,3,4],[4,5,6]],[[7,8,9],[10,11,12]]])) 
Out[49]: 81 
1

Это расширение для answer post above by Akavall. Из этого ответа вы можете видеть, что np.sum выполняет быстрее для np.array объектов, тогда как sum выполняет быстрее для list объектов.С расширением на это:

Запуск np.sum для объекта np.arrayVs.sum для объекта list, кажется, что они выполняют шею до шеи.

# I'm running IPython 

In [1]: x = range(1000) # list object 

In [2]: y = np.array(x) # np.array object 

In [3]: %timeit sum(x) 
100000 loops, best of 3: 14.1 µs per loop 

In [4]: %timeit np.sum(y) 
100000 loops, best of 3: 14.3 µs per loop 

Выше sumявляется крошечным немного быстрее, чем np.array, хотя, иногда я видел np.sum таймингов быть 14.1 µs тоже. Но в основном это 14.3 µs.

Смежные вопросы