Python если еще микро-оптимизация - PullRequest
3 голосов
/ 25 декабря 2009

В размышлениях об оптимизации кода мне было интересно, что в python дороже:

if x:
    d = 1
else:
    d = 2

или

d = 2
if x:
    d = 1

Есть мысли? Мне нравится уменьшенное количество строк во втором, но мне было интересно, было ли переназначение более дорогостоящим, чем переключение условий.

Ответы [ 4 ]

20 голосов
/ 25 декабря 2009

Не вдумайтесь, не удивляйтесь, измерьте - с timeit в командной строке оболочки (безусловно, лучший, самый простой способ использовать его!) , Python 2.5.4 на Mac OSX 10.5 на ноутбуке ...:

$ python -mtimeit -s'x=0' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0748 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0685 usec per loop
$ python -mtimeit -s'x=0' 'd=2' 'if x: d=1'
10000000 loops, best of 3: 0.0734 usec per loop
$ python -mtimeit -s'x=1' 'd=2' 'if x: d=1'
10000000 loops, best of 3: 0.101 usec per loop

Итак, вы видите: форма "просто-если" может сэкономить 1,4 наносекунды, когда x ложно, но стоит 40,2 наносекунды, если x истинно, по сравнению с формой "если / еще"; поэтому, в контексте микрооптимизации, вы должны использовать первое, только если x в 30 раз больше шансов быть ложным, чем истиной, или около того. Кроме того:

$ python -mtimeit -s'x=0' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0736 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.076 usec per loop

... у троичного оператора if / else есть свои собственные плюсы и минусы.

Когда различия настолько малы, что вы должны многократно измерять, устанавливать уровень шума и следить за тем, чтобы различия в уровне шума не воспринимались как значимые. Например, чтобы сравнить оператор с выражением if / else в случае «x is true», повторите каждое несколько раз:

$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.076 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0749 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0742 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0749 usec per loop
$ python -mtimeit -s'x=1' 'd=1 if x else 2'
10000000 loops, best of 3: 0.0745 usec per loop

теперь вы можете утверждать, что формы выражения принимают (на этом компьютере и в версиях ключевого программного обеспечения) от 74,2 до 76,0 наносекунд - диапазон гораздо более выразителен, чем любое отдельное число. И аналогично:

$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0688 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0681 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0687 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0679 usec per loop
$ python -mtimeit -s'x=1' 'if x: d=1' 'else: d=2'
10000000 loops, best of 3: 0.0692 usec per loop

теперь Вы можете с уверенностью утверждать, что форма заявления занимает (при идентичных условиях) 67,9–69,2 наносекунды; таким образом, его преимущество для x true по сравнению с формой выражения составляет от 4,8 до 8,1 наносекунд (вполне справедливо ограничить эту последнюю оценку интервала 6,3-6,8 наносекундами, сравнивая мин / мин и макс / макс вместо мин / макс и макс / min, как более широкая, более пруденциальная оценка).

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

5 голосов
/ 25 декабря 2009

Вероятно, вы должны сравнить это, но есть и третья форма, которая использует троичный оператор:

d = 1 if x else 2
2 голосов
/ 25 декабря 2009

Второй, очевидно, должен быть более дорогим, он выполняет те же операции, если x равен false, и в два раза больше присваиваний, если x - true.

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

1 голос
/ 25 декабря 2009

Я бы сказал, что наиболее читаемый - самый оптимизированный (по крайней мере, для читабельности).

Конструкция if ... else проясняет, что вы имеете дело с / или кейсом.

Конструкция присваивания может иметь больше смысла, если (d == 2) является обычным значением, а ваше if проверяет необычный случай. Эта конструкция становится менее понятной, если ваше назначение удалено от if.

В этом простом примере это не имеет значения. Для более сложного кода я почти всегда оптимизировал бы его для удобочитаемости, даже за счет нескольких циклов ЦП.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...