Вопрос по python, performance, osx-leopard, indexing – Эффективность индексирования списков (python 2 против python 3)

27

Отвечая другомувопросЯ предложил использоватьtimeit проверить разницу между индексированием списка с положительными целыми числами и отрицательными целыми числами. Вот код:

import timeit
t=timeit.timeit('mylist[99]',setup='mylist=list(range(100))',number=10000000)
print (t)
t=timeit.timeit('mylist[-1]',setup='mylist=list(range(100))',number=10000000)
print (t)

Я запустил этот код с Python 2.6:

$ python2.6 test.py
0.587687015533
0.586369991302

Затем я запустил его с Python 3.2:

$ python3.2 test.py
0.9212150573730469
1.0225799083709717

Затем я почесал голову, немного поискал в Google и решил опубликовать эти наблюдения здесь.

Операционная система: OS-X (10.5.8) - Intel Core2Duo

Это кажется довольно существенной разницей для меня (в 1,5 раза). У кого-нибудь есть идея, почему python3 намного медленнее - особенно для такой распространенной операции?

EDIT

Я запустил один и тот же код на своем настольном компьютере с Ubuntu Linux (Intel i7) и достиг сопоставимых результатов с python2.6 и python 3.2. Кажется, что это проблема, которая зависит от операционной системы (или процессора) (другие пользователи видят такое же поведение на компьютерах с Linux - см. Комментарии).

EDIT 2

Стартовый баннер был запрошен в одном из ответов, поэтому здесь идет:

Python 2.6.4 (r264:75821M, Oct 27 2009, 19:48:32) 
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin

а также:

Python 3.2 (r32:88452, Feb 20 2011, 10:19:59) 
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin

UPDATE

Я только что установил свежие версии python2.7.3 и python3.2.3 изhttp://www.python.org/download/

В обоих случаях я взял

"Python x.x.3 Mac OS X 32-bit i386/PPC Installer (for Mac OS X 10.3 through 10.6 [2])"

так как я на OS X 10.5. Вот новые сроки (которые достаточно последовательны в нескольких испытаниях):

Python 2.7

$python2.7 test.py
0.577006101608
0.590042829514

Python 3.2.3

$python3.2 test.py
0.8882801532745361
1.034242868423462
@OttoAllmendinger - это согласуется с некоторыми из ответов (гораздо большая разница в OS-X и Linux). Возможно, ты прав. mgilson
@mgilson Я получаю примерно одинаковые результаты на моей машине с Linux Otto Allmendinger
@AshwiniChaudhary - все это вsetup который не получает время.xrange противrange не должен иметь ничего общего с этим. mgilson
Для справки: естьthis ответ на вопрос об отсутствии специального целого числа маленьких целых чисел в python3.0, возможно, он до сих пор отсутствует в python3.2 Otto Allmendinger
попробуйте использоватьxrange() в Python 2.x Ashwini Chaudhary

Ваш Ответ

3   ответа
4

$ python
Python 2.7.3 (default, Apr 20 2012, 22:44:07) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> t=timeit.timeit('mylist[99]',setup='mylist=list(range(100))',number=50000000)
>>> print (t)
2.55517697334
>>> t=timeit.timeit('mylist[99L]',setup='mylist=list(range(100))',number=50000000)
>>> print (t)
3.89904499054

$ python3
Python 3.2.3 (default, May  3 2012, 15:54:42) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import timeit
>>> t=timeit.timeit('mylist[99]',setup='mylist=list(range(100))',number=50000000)
>>> print (t)
3.9906489849090576

python3 не имеет старого типа int.

Ницца. Быстрый поиск показал публикацию об ускорении в Python 3.1, потому что он намного медленнее, чем 2.x int, но, к сожалению, сам сайт недоступен. Более тщательный поиск, вероятно, в точности повлечет за собой то, что они сделали, чтобы исправить положение вещей, и, возможно, почему это не очень помогло для 32-битной системы. Но я могу представить множество возможностей. Например, для 64-битных слов трюки, в которых маленькие длинные слова помещаются в одно слово, не требуют одновременного чтения символа & # x2026;
Очень интересно. Использование длинных целых дает результаты синхронизацииvery похож на версию Python 3.x. mgilson
0

range() это Питон 2xrange(), Если вы хотите смоделировать Python 2range() в коде , вы должны использоватьlist(range(num), Чем большеnum есть, большая разница будет наблюдаться с вашим исходным кодом.

Индексирование должно быть независимым от того, что хранится в списке, поскольку в списке хранятся только ссылки на целевые объекты. Ссылки нетипизированы и имеют одинаковый вид. Следовательно, тип списка представляет собой однородную структуру данных - технически. Индексирование означает превращение значения индекса в начальный адрес + смещение. Вычисление смещения очень эффективно с максимум одним вычитанием. Это очень дешевая дополнительная операция по сравнению с другими операциями.

@mgilson; +1, ты прав. Я должен читать лучше в следующий раз;)
sigh - мы уже прошли через это.setup часть времени не получает времени. В моей настройке я используюlist(range(num))поэтому то, что рассчитывается (в обоих случаях), это список чисел, а не объект диапазона. И я понимаю вещи во втором абзаце. Вопрос в том, почему все эти операции с использованием python3.x выполняются намного медленнее, чем в python 2.x? mgilson
24

что это артефакт некоторых сборок Python 3.2. На данный момент лучшая гипотеза заключается в том, что все 32-разрядные сборки Intel имеют замедление, но не 64-разрядные. Продолжайте читать для дальнейших деталей.

Вы не выполнили достаточно тестов, чтобы что-то определить. Повторяя тест несколько раз, я получал значения от 0,31 до 0,54 для одного теста, что является огромным отклонением.

Итак, я провел ваш тест с10x число иrepeat=10, используя несколько разных установок Python2 и Python3. Отбрасывание верхнего и нижнего результатов, усреднение остальных 8 и деление на 10 (чтобы получить число, эквивалентное вашим тестам), вот что я увидел:

 1. 0.52/0.53 Lion 2.6
 2. 0.49/0.50 Lion 2.7
 3. 0.48/0.48 MacPorts 2.7
 4. 0.39/0.49 MacPorts 3.2
 5. 0.39/0.48 HomeBrew 3.2

Итак, похоже, что 3.2 на самом деле немного быстрее с[99]и примерно с той же скоростью[-1].

Однако на машине 10.5 я получил следующие результаты:

 1. 0.98/1.02 MacPorts 2.6
 2. 1.47/1.59 MacPorts 3.2

Вернувшись на оригинальную (Lion) машину, я запустил 32-битный режим и получил:

 1. 0.50/0.48 Homebrew 2.7
 2. 0.75/0.82 Homebrew 3.2

Итак, кажется, что важна 32-битность, а не Leopard против Lion, gcc 4.0 против gcc 4.2 или clang, аппаратные различия и т. Д. Это поможет протестировать 64-битные сборки под Leopard, с разными компиляторами и т. Д. ., но, к сожалению, мой Leopard - это Intel Mini первого поколения (с 32-разрядным процессором Core Solo), поэтому я не могу выполнить этот тест.

Как еще одно косвенное доказательство, я провел множество других быстрых тестов на Lion box, и похоже, что 32-разрядная версия 3.2 на 50% медленнее, чем 2.x, а 64-разрядная версия 3.2, возможно, немного быстрее, чем 2. Икс. Но если мы действительно хотим поддержать это, кто-то должен выбрать и запустить настоящий набор тестов.

В любом случае, я думаю, что при оптимизации ветки 3.x никто не прикладывает особых усилий к 32-битным сборкам i386 Mac. Что на самом деле является разумным выбором для них.

Или, в качестве альтернативы, они даже не приложили много усилий к 32-битному периоду i386. Эта возможность может объяснить, почему OP видел 2.x и 3.2, давая аналогичные результаты на Linux-боксе, в то время как Otto Allmendinger видел, что 3.2 аналогично медленнее, чем 2.6 на Linux-боксе. Но поскольку ни один из них не упомянул, работали ли они с 32-разрядной или 64-разрядной системой Linux, трудно понять, насколько это актуально.

Есть еще много других различных возможностей, которые мы не исключили, но это кажется лучшей.

+1 для 10X и повтор = 10
Хорошо, правда; Если вы хотите знатьwhy это медленнее, чем вам придется просматривать исходный код и / или профилировать интерпретатор и / или просматривать архивы списка python-dev, и все это требует больше усилий, чем я хочу в данный момент добавить ». # x2026;
Я устанавливаю текущие MacPorts 2.6 и 3.2 на машину 10.5, на что уйдет вечность & # x2026; но через час после этого я проведу тест там и посмотрим, что произойдет. Если он не воспроизводит ваши результаты, это должно убедительно доказать, что что-то странное в вашей сборке 3.2, а не в 3.2 вообще. Если это так, есть место для дополнительного расследования.
Во-первых, это отличный ответ (+1), хотя я не уверен на 100%, что в этом причина. Я разместил стартовый баннер и процессор для моих двух машин. Насколько я могу судить, похоже, что я установил обе версии Python из одного места, скомпилированные с помощью одного и того же компилятора. Если кто-то другой сможет воспроизвести ваш тест с использованием OS-X 10.5.8, я, вероятно, буду убежден. (если больше ничего не произойдет, я, вероятно, все равно приму этот ответ - это отличный ответ). mgilson
Оба должны быть 32-битными. OS-X 10.5.8 - это 32-битная ОС, поэтому я не смогу запустить 64-битную версию, если бы захотел. mgilson

Похожие вопросы