Массив python nums vs list

Мне нужно выполнить некоторые вычисления большим списком чисел.

Помогает ли array.array или numpy.array значительно повысить производительность по сравнению с типичными массивами?

Мне не нужно делать сложные манипуляции на массивах, мне просто нужно иметь доступ и изменять значения,

например.

import numpy
x = numpy.array([0] * 1000000)
for i in range(1,len(x)):
  x[i] = x[i-1] + i

Так что мне действительно не понадобится конкатенация, нарезка и т.д.

Кроме того, похоже, что массив выдает ошибку, если я пытаюсь назначить значения, которые не соответствуют длине C:

import numpy
a = numpy.array([0])
a[0] += 1232234234234324353453453
print(a)

На консоли я получаю:

a[0] += 1232234234234324353453453
OverflowError: Python int too large to convert to C long

Есть ли вариант массива, который позволяет мне вводить неограниченные целые числа на Python? Или это так уберет точку с наличием массивов в первую очередь?

Ответ 1

Ваш первый пример может ускориться. Цикл Python и доступ к отдельным элементам в массиве numpy медленны. Вместо этого используйте векторизованные операции:

import numpy as np
x = np.arange(1000000).cumsum()

Вы можете поместить неограниченные целые числа Python в массив numpy:

a = np.array([0], dtype=object)
a[0] += 1232234234234324353453453

Арифметические операции по сравнению с целыми числами C с фиксированным размером будут в этом случае медленнее.

Ответ 2

Сначала вам нужно понять разницу между массивами и списками.

Массив - это непрерывный блок памяти, состоящий из элементов некоторого типа (например, целых чисел).

Вы не можете изменить размер массива после его создания.
Отсюда следует, что каждый целочисленный элемент в массиве имеет фиксированный размер, например. 4 байта.

С другой стороны, список - это просто "массив" адресов (которые также имеют фиксированный размер).

Но тогда каждый элемент содержит адрес чего-то еще в памяти, который является фактическим целым, с которым вы хотите работать. Конечно, размер этого целого не имеет значения для размера массива. Таким образом, вы всегда можете создать новое (большее) целое число и "заменить" старое, не затрагивая размер массива, который просто содержит адрес целого числа.

Конечно, это удобство списка стоит дорого: для выполнения арифметики для целых чисел теперь требуется доступ к памяти для массива, плюс доступ к памяти для самого целого, плюс время, необходимое для выделения большего объема памяти (при необходимости), плюс время, необходимое для удаления старого целого (при необходимости). Так что да, это может быть медленнее, поэтому вам нужно быть осторожным, что вы делаете с каждым целым числом внутри массива.

Ответ 3

Для большинства применений списки полезны. Иногда, например, удобнее работать с массивами numpy.

a=[1,2,3,4,5,6,7,8,9,10]

b=[5,8,9]

Рассмотрим список "а", и если вы хотите получить доступ к элементам в списке по отдельным индексам, указанным в списке "б" записи

a[b]

не будет работать.

но когда вы используете их как массивы, вы можете просто написать

a[b]

получить вывод в виде массива ([6,9,10]).

Ответ 4

Сделайте массив array.array или numpy.array значительно повышающим производительность типичные массивы?

Я попытался немного проверить это с помощью следующего кода:

import timeit, math, array
from functools import partial
import numpy as np

# from the question
def calc1(x):
    for i in range(1,len(x)):
        x[i] = x[i-1] + 1

# a floating point operation
def calc2(x):
    for i in range(0,len(x)):
        x[i] = math.sin(i)

L = int(1e5)

# np
print('np 1: {:.5f} s'.format(timeit.timeit(partial(calc1, np.array([0] * L)), number=20)))
print('np 2: {:.5f} s'.format(timeit.timeit(partial(calc2, np.array([0] * L)), number=20)))

# np but with vectorized form
vfunc = np.vectorize(math.sin)
print('np 2 vectorized: {:.5f} s'.format(timeit.timeit(partial(vfunc, np.arange(0, L)), number=20)))

# with list
print('list 1: {:.5f} s'.format(timeit.timeit(partial(calc1, [0] * L), number=20)))
print('list 2: {:.5f} s'.format(timeit.timeit(partial(calc2, [0] * L), number=20)))

# with array
print('array 1: {:.5f} s'.format(timeit.timeit(partial(calc1, array.array("f", [0] * L)), number=20)))
print('array 2: {:.5f} s'.format(timeit.timeit(partial(calc2, array.array("f", [0] * L)), number=20)))

И результаты состояли в том, что список выполняется быстрее всего (Python 3.3, NumPy 1.8):

np 1: 2.14277 s
np 2: 0.77008 s
np 2 vectorized: 0.44117 s
list 1: 0.29795 s
list 2: 0.66529 s
array 1: 0.66134 s
array 2: 0.88299 s

Это кажется противоречивым. Кажется, что нет никаких преимуществ при использовании numpy или array над list для этих простых примеров.

Ответ 5

Помогает ли array.array или numpy.array значительно повысить производительность по сравнению с типичными массивами?

Он может, в зависимости от того, что вы делаете.

Или это сделало бы так, чтобы в первую очередь убрать точку с массивами?

В значительной степени, да.

Ответ 6

используйте a=numpy.array(number_of_elements, dtype=numpy.int64), который должен предоставить вам массив из 64-битных целых чисел. Они могут хранить любое целое число между -2 ^ 63 и (2 ^ 63) -1 (приблизительно между -10 ^ 19 и 10 ^ 19), которое обычно более чем достаточно.

Ответ 7

Для OP: Для вашего варианта использования списки использования.

Мои правила, когда использовать которые, учитывая надежность и скорость:

список: (самый надежный, самый быстрый для изменчивых случаев) Когда ваш список постоянно мутирует, как в симуляции физики. Когда вы "создаете" данные с нуля, это может быть непредсказуемым по своей природе.

np.arrary: (менее надежный, самый быстрый для линейной алгебры и постобработки данных) Пример. Когда вы выполняете "постобработку" набора данных, который вы уже собрали с помощью датчиков или моделирования; выполнение операций, которые могут быть векторизованы.