Встроенный диапазон или numpy.arange: что более эффективно?
При повторении большого массива с выражением диапазона, следует ли использовать встроенную функцию диапазона Python или numpy arange
, чтобы получить максимальную производительность?
Мои рассуждения до сих пор:
arange
, вероятно, прибегает к собственной реализации и может быть быстрее. С другой стороны, arange
возвращает полный массив, который занимает память, поэтому могут быть накладные расходы. Выражение диапазона Python 3 является генератором, который не сохраняет все значения в памяти.
Ответы
Ответ 1
Для больших массивов numpy должно быть более быстрым решением.
В numpy вы должны использовать комбинации векторизованных вычислений, ufuncs и indexing, чтобы решить ваши проблемы, так как он работает со скоростью C
.
Зацикливание по массивам numpy неэффективно по сравнению с этим.
(Что-то вроде худшего, что вы могли бы сделать, это перебрать массив с индексом, созданным с помощью range
или np.arange
, как предлагает первое предложение в вашем вопросе, но я не уверен, действительно ли вы имеете в виду что.)
import numpy as np
import sys
sys.version
# out: '2.7.3rc2 (default, Mar 22 2012, 04:35:15) \n[GCC 4.6.3]'
np.version.version
# out: '1.6.2'
size = int(1E6)
%timeit for x in range(size): x ** 2
# out: 10 loops, best of 3: 136 ms per loop
%timeit for x in xrange(size): x ** 2
# out: 10 loops, best of 3: 88.9 ms per loop
# avoid this
%timeit for x in np.arange(size): x ** 2
#out: 1 loops, best of 3: 1.16 s per loop
# use this
%timeit np.arange(size) ** 2
#out: 100 loops, best of 3: 19.5 ms per loop
Итак, для этого случая numpy в 4 раза быстрее, чем при использовании xrange
, если вы это сделаете правильно. В зависимости от вашей проблемы numpy может быть намного быстрее, чем в 4 или 5 раз быстрее.
Ответ на этот вопрос объясняет еще несколько преимуществ использования массивов numpy вместо списков python для больших наборов данных.
Ответ 2
Прежде всего, как написано @bmu, вы должны использовать комбинации векторизованных вычислений, ufuncs и индексации. Есть действительно некоторые случаи, когда требуется явный цикл, но они действительно редки.
Если явный цикл необходим, с python 2.6 и 2.7, вы должны использовать xrange (см. ниже). Из того, что вы говорите, в Python 3 диапазон совпадает с xrange (возвращает генератор). Поэтому, возможно, диапазон подходит для вас.
Теперь вы должны попробовать сами
(используя timeit: - здесь "волшебная функция" ipython):
%timeit for i in range(1000000): pass
[out] 10 loops, best of 3: 63.6 ms per loop
%timeit for i in np.arange(1000000): pass
[out] 10 loops, best of 3: 158 ms per loop
%timeit for i in xrange(1000000): pass
[out] 10 loops, best of 3: 23.4 ms per loop
Опять же, как упоминалось выше, большую часть времени можно использовать формулу numpy vector/array (или ufunc и т.д.), которые запускают скорость c: намного быстрее. Это то, что мы могли бы назвать "векторным программированием". Это упрощает реализацию программы, чем C (и более читаемо), но почти так же быстро в конце.