Почему вычитание быстрее, чем дополнение в Python?

Это уже завоевало популярность с, Отображают/уменьшают в Hadoop

34
задан Statto 8 September 2009 в 22:01
поделиться

9 ответов

$ python -m timeit -s "x=0" "x+=1"
10000000 loops, best of 3: 0.151 usec per loop
$ python -m timeit -s "x=0" "x-=-1"
10000000 loops, best of 3: 0.154 usec per loop

Похоже, у вас есть некоторая погрешность измерения

13
ответ дан 27 November 2019 в 16:05
поделиться

«Второй цикл надежно быстрее ...»

Вот ваше объяснение. Измените порядок вашего сценария так, чтобы сначала был рассчитан тест на вычитание, затем затем сложение, и внезапно сложение снова стало более быстрой операцией:

-= 3.05
+= 2.84

Очевидно, что-то происходит со второй половиной сценария, что делает его быстрее. Мое предположение заключается в том, что первый вызов range () выполняется медленнее, потому что python необходимо выделить достаточно памяти для такого длинного списка, но он может повторно использовать эту память для второй вызов range () :

import time
start = time.clock()
x = range(10000000)
end = time.clock()
del x
print 'first range()',end-start
start = time.clock()
x = range(10000000)
end = time.clock()
print 'second range()',end-start

Несколько запусков этого скрипта показывают, что дополнительное время, необходимое для первого range () , составляет почти всю разницу во времени между ' + = 'и' - = 'видно выше:

first range() 0.4
second range() 0.23
5
ответ дан 27 November 2019 в 16:05
поделиться

Когда вы задаете вопрос, всегда полезно сказать, какую платформу и какую версию Python вы используете. Иногда это не имеет значения. Это НЕ один из тех случаев:

  1. time.clock () подходит только для Windows. Отбросьте свой собственный измерительный код и используйте -m timeit , как показано в ответе pixelbeat.

  2. Python 2.X range () создает список. Если вы используете Python 2.x, замените range на xrange и посмотрите, что произойдет.

  3. Python 3.X int - это Python2.X ] long .

4
ответ дан 27 November 2019 в 16:05
поделиться

Я думаю, что «общий урок программирования» состоит в том, что действительно трудно предсказать, только глядя на исходный код, какая последовательность операторов будет самой быстрой. Программисты всех уровней часто попадают в ловушку такого рода «интуитивной» оптимизации. То, что вы думаете, что вы знаете, не обязательно может быть правдой.

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

Для языков с байтовой компиляцией, таких как Java, Python и .NET, недостаточно даже измерить производительность только одна машина. Различия между версиями виртуальных машин, реализациями трансляции собственного кода, оптимизацией для ЦП,

7
ответ дан 27 November 2019 в 16:05
поделиться

Самая большая проблема с Python 2.5 заключается в использовании диапазона, который будет выделять большой список для перебора. При использовании xrange, что бы ни было сделано вторым, для меня это немного быстрее. (Не уверен, что диапазон стал генератором в Python 3.)

0
ответ дан 27 November 2019 в 16:05
поделиться

Ваш эксперимент ошибочен. Этот эксперимент должен быть разработан таким образом, чтобы написать 2 разные программы - 1 для сложения, 1 для вычитания. Они должны быть точно такими же и выполняться в одинаковых условиях с данными, помещаемыми в файл. Затем вам нужно усреднить прогоны (по крайней мере, несколько тысяч), но вам понадобится статистик, который назовет вам подходящее число.

Если вы хотите проанализировать различные методы сложения, вычитания и цикла, снова каждый из них должна быть отдельной программой.

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

0
ответ дан 27 November 2019 в 16:05
поделиться

Это было бы замечательно, поэтому у меня тщательно оценил ваш код, а также установил срок действия, так как я считаю его более правильным (все объявления и вызовы функций вне цикла). Обе версии я запускал пять раз.

  • Выполнение кода подтвердило ваши утверждения: - = занимает все меньше времени; В среднем 3,6%
  • Однако выполнение моего кода противоречит результату вашего эксперимента: + = занимает в среднем (не всегда) на 0,5% меньше времени.

Чтобы показать все результаты, я разместил графики в Интернете:

Итак, я прихожу к выводу, что ваш эксперимент имеет предвзятость, и это важно.

Наконец, вот мой код:

import time

addtimes = [0.] * 100
subtracttimes = [0.] * 100

range100 = range(100)
range10000000 = range(10000000)

j = 0
i = 0
x = 0
start = 0.


for j in range100:
 start = time.clock()
 x = 0
 for i in range10000000:
  x += 1
 addtimes[j] = time.clock() - start

for j in range100:
 start = time.clock()
 x = 0
 for i in range10000000:
  x -= -1
 subtracttimes[j] = time.clock() - start

print '+=', sum(addtimes)
print '-=', sum(subtracttimes)
0
ответ дан 27 November 2019 в 16:05
поделиться

Я могу воспроизвести это на моем Q6600 (Python 2.6.2); увеличение диапазона до 100000000:

('+=', 11.370000000000001)
('-=', 10.769999999999998)

Сначала несколько наблюдений:

  • Это 5% для тривиальной операции. Это важно.
  • Скорость кодов операций сложения и вычитания не имеет значения. Это уровень шума, полностью затмеваемый оценкой байт-кода. Речь идет об одной или двух собственных инструкциях, около тысячи.
  • Байт-код генерирует точно такое же количество инструкций; единственная разница - INPLACE_ADD vs. INPLACE_SUBTRACT и +1 против 1.

Глядя на исходный код Python, я могу сделать предположение. Это обрабатывается в ceval.c, в PyEval_EvalFrameEx . INPLACE_ADD имеет значительный дополнительный блок кода для обработки конкатенации строк. Этот блок не существует в INPLACE_SUBTRACT , поскольку вы не можете вычитать строки. Это означает, что INPLACE_ADD содержит больше собственного кода. В зависимости (в значительной степени!) От того, как код генерируется компилятором, этот дополнительный код может быть встроен в остальную часть кода INPLACE_ADD, что означает, что добавления могут сильнее ударить по кешу инструкций, чем вычитание. Это могло вызывать дополнительные попадания в кэш L2, что могло вызвать значительную разницу в производительности.

Это сильно зависит от системы, в которой вы находитесь (разные процессоры имеют разное количество кешей и архитектур кешей), используемого компилятора, включая конкретную версию и параметры компиляции (разные компиляторы по-разному решают, какие части кода на критическом пути, который определяет, как ассемблерный код объединяется в кучу) и т. д.

Кроме того, в Python 3.0.1 разница обратная (+: 15.66, -: 16.71); без сомнения, эта критическая функция сильно изменилась.

и т. д.

Кроме того, в Python 3.0.1 разница обратная (+: 15.66, -: 16.71); без сомнения, эта критическая функция сильно изменилась.

и т. д.

Кроме того, в Python 3.0.1 разница обратная (+: 15.66, -: 16.71); без сомнения, эта критическая функция сильно изменилась.

77
ответ дан 27 November 2019 в 16:05
поделиться

Обратный цикл выполняется быстрее, потому что компьютер имеет более легкий сравнение времени, если число равно 0.

-1
ответ дан 27 November 2019 в 16:05
поделиться
Другие вопросы по тегам:

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