2013-07-23 2 views
4

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

Например это более эффективно:

a = 50 
b = a*12-1 
c = a*b 

print c 
#some code 
print c*100 + 10 
#some code 
print c/100 + 20 
#etc 

Чем это:

print 50*(50*12-1) 
#some code 
print 50*(50*12-1) * 100 + 10 
#some code 
print 50*(50*12-1)/100 + 20 
#etc 
+0

Вы говорите о повторяющихся выражениях, которые включают только литералы (т. Е. Неотъемлемо постоянные значения), как и ваш пример выше? –

+2

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

ответ

2

Казаться любит довольно незначительную скорость до меня:

> python -m timeit 'a = 50; b = a*12-1; c = a*b; c; c*100+10; c/100+20;' 
1000000 loops, best of 3: 0.27 usec per loop 
> python -m timeit '50*(50*12-1); 50*(50*12-1) * 100 + 10; 50*(50*12-1)/100 + 20' 
1000000 loops, best of 3: 0.218 usec per loop 

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

редактировать: Я думаю, что это то, что имел в виду gnibbler в комментариях, но это все еще медленнее:

> python -m timeit 'def x(): a = 50; b = a*12-1; c = a*b; c; c*100+10; c/100+20;' 'x()' 
1000000 loops, best of 3: 0.428 usec per loop 

edit2: Это на самом деле то, что имел в виду gnibbler в комментариях, и разница по-прежнему negligle. Замечания об использовании более читаемым один по-прежнему держать:

> python -m timeit -s 'def x(): a = 50; b = a*12-1; c = a*b; c; c*100+10; c/100+20;' 'x()' 
1000000 loops, best of 3: 0.367 usec per loop 
> python -m timeit -s 'def x(): 50*(50*12-1); 50*(50*12-1) * 100 + 10; 50*(50*12-1)/100 + 20' 'x()' 
1000000 loops, best of 3: 0.278 usec per loop 
+0

глобальные поисковые запросы медленнее. Вы должны попробовать это внутри функции. –

+0

Вид. Вы пропустили '-s' для определения функции. Я имел в виду, что вы также запускали буквальную версию только в функции, чтобы получить осмысленное сравнение. Причина, по которой она выглядит медленнее, заключается в том, что теперь вы добавляете служебные функции. Но поскольку этот материал обычно выполняется внутри функции, вам нужно убедиться, что вы сравниваете поиск переменных внутри функций. –

+1

Если вы используете 'dis.dis (x)', вы можете видеть, что оптимизатор глазок сокращает всю математику до констант в 'def x(): 50 * (50 * 12-1); 50 * (50 * 12-1) * 100 + 10; 50 * (50 * 12-1)/100 + 20' (по крайней мере, в python3.3) –

0

Буквальный будет быстрее просто потому, что он не должен относиться к чему-либо. Там нет предварительной обработки в Python, так что вы не можете сделать #define как в C.

+0

, но не будет ли он пересчитывать выражение 50 * (50 * 12-1) каждый раз? – Bitwise

+0

Вы знаете, что, я действительно верю, что я на самом деле предварительно обработал это в своей голове, так что каждое событие 50 * (50 * 12-1) было, по моему воображению, 29950. :) – hoosierEE

7

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

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

например.

$ python3.3 
Python 3.3.0 (default, Sep 29 2012, 17:17:45)  
[GCC 4.7.2] on linux 
Type "help", "copyright", "credits" or "license" for more information. 
>>> def x(): 
...  50*(50*12-1) 
...  50*(50*12-1) * 100 + 10 
...  50*(50*12-1)/100 + 20 
... 
>>> dis.dis(x) 
    2   0 LOAD_CONST    9 (29950) 
       3 POP_TOP    

    3   4 LOAD_CONST    14 (2995010) 
       7 POP_TOP    

    4   8 LOAD_CONST    19 (319.5) 
      11 POP_TOP    
      12 LOAD_CONST    0 (None) 
      15 RETURN_VALUE   

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

Смежные вопросы