Форум сайта python.su
По логике, скорость доступа к массивам должна быть выше, а тут лист всех порвал.
# coding:utf8
import array
from time import time
import numpy as np
COUNT = 10**7
l = [0 for i in xrange(COUNT)]
t = tuple(l)
a = array.array('l',l)
n = np.zeros(COUNT)
def calc_delta():
t1 = time()
for i in xrange(COUNT):
pass
return (time() - t1) * 1000
delta = calc_delta()
def sm(x):
t1 = time()
for i in xrange(COUNT):
x[i]
print type(x), (time() - t1) * 1000 - delta
sm(l)
sm(t)
sm(a)
sm(n)
<type 'list'> 300.084114075
<type 'tuple'> 530.132055283
<type 'array.array'> 667.308330536
<type 'numpy.ndarray'> 1605.17811775
Отредактировано (Июль 23, 2011 13:07:48)
Офлайн
1. list в Питоне имеет константное время доступа к элементу. Зато вставка-удаление — O(N).
2. Если уж меряем — то давайте делать это более корректно. В вашем случае первый выигрывает.
import array
import numpy
import random
import sys
import timeit
from collections import defaultdict
COUNT = 10**7
a = (list(xrange(COUNT)), tuple(xrange(COUNT)),
array.array('l', list(xrange(COUNT))),
numpy.zeros(COUNT))
def f(collection, count):
l = len(collection)
for i in xrange(count):
ind = random.randint(0, l-1)
collection[ind]
print '-' * 80
res = defaultdict(list)
for i in xrange(100):
col = random.choice(a)
res[type(col)].append(timeit.timeit("f(col, 100)", "from __main__ import f, col",
number=1000))
sys.stdout.write('.')
sys.stdout.flush()
for key, val in res.iteritems():
print key, sum(val) / len(val)
Офлайн
Андрей СветловВсе примерно равны потому что вы меряете скорость рандома:
Что больше похоже на правду — все примерно равноценны.
for i in xrange(count):
ind = random.randint(0, l-1)
Офлайн
И то верно. Ступил.
Поправил:
import array
import numpy
import random
import sys
import timeit
from collections import defaultdict
COUNT = 10**7
a = (list(xrange(COUNT)), tuple(xrange(COUNT)),
array.array('l', list(xrange(COUNT))),
numpy.zeros(COUNT))
indices = random.sample(a[0], 1000)
def f(collection, indices=indices):
for i in indices:
collection[i]
print('-' * 80)
res = defaultdict(list)
for i in xrange(100):
col = random.choice(a)
res[type(col)].append(timeit.timeit("f(col)", "from __main__ import f, col",
number=1000))
sys.stdout.write('.')
sys.stdout.flush()
print('')
for key, val in res.iteritems():
print(key, sum(val) / len(val))
Офлайн
Судя по всему дело в оптимизации:
case BINARY_SUBSCR:
w = POP();
v = TOP();
if (PyList_CheckExact(v) && PyInt_CheckExact(w)) {
/* INLINE: list[int] */
Py_ssize_t i = PyInt_AsSsize_t(w);
if (i < 0)
i += PyList_GET_SIZE(v);
if (i >= 0 && i < PyList_GET_SIZE(v)) {
x = PyList_GET_ITEM(v, i);
Py_INCREF(x);
}
else
goto slow_get;
}
else
slow_get:
x = PyObject_GetItem(v, w);
Офлайн
Вот код получения элемента из тупла, берется напрямую из массива - должен работать быстро…
PyObject *
PyTuple_GetItem(register PyObject *op, register Py_ssize_t i)
{
if (!PyTuple_Check(op)) {
PyErr_BadInternalCall();
return NULL;
}
if (i < 0 || i >= Py_SIZE(op)) {
PyErr_SetString(PyExc_IndexError, "tuple index out of range");
return NULL;
}
return ((PyTupleObject *)op) -> ob_item[i];
}
Офлайн
ZAN прав. Для tuple берется не PyTuple_GetItem а tuplesubscript из того же файла.
Офлайн
Для должной точности надо уменьшить количество вызовов функции f и увеличить выборку для индексов в цикле функции f и тогда array оказывается впереди планеты всей.
К примеру:
indices = random.sample(a[0], 100000)
res[type(col)].append(timeit.timeit("f(col)", "from __main__ import f, col",
number=10))
Отредактировано (Июль 25, 2011 08:00:19)
Офлайн
IsemУ меня результаты прежние, лист всех обгоняет
Для должной точности надо уменьшить количество вызовов функции f и увеличить выборку для индексов в цикле функции f и тогда array оказывается впереди планеты всей.
(<type 'list'>, 0.33289950370788574)
(<type 'array.array'>, 0.38352442741394044)
(<type 'numpy.ndarray'>, 0.44202763693673269)
(<type 'tuple'>, 0.57573616504669189)
Офлайн
IsemДля точности нужно исключить затрачиваемое время на list в каждом тесте:
Для должной точности надо ,,,
for i in indices:
Отредактировано (Июль 25, 2011 09:38:29)
Офлайн