Почему функция `float` медленнее, чем умножение на 1.0?

Я понимаю, что это можно утверждать как проблему без проблем, но я пишу программное обеспечение для сред HPC, поэтому это увеличение скорости на 3,5 раза на самом деле имеет значение.

In [1]: %timeit 10 / float(98765) 1000000 loops, best of 3: 313 ns per loop In [2]: %timeit 10 / (98765 * 1.0) 10000000 loops, best of 3: 80.6 ns per loop 

Я использовал, чтобы посмотреть код, и я полагаю, что float() будет медленнее, поскольку для этого требуется вызов функции (к сожалению, я не мог dis.dis(float) чтобы посмотреть, что он на самом деле делает).

Я предполагаю, что второй вопрос будет, когда следует использовать float(n) и когда следует использовать n * 1.0 ?

One Solution collect form web for “Почему функция `float` медленнее, чем умножение на 1.0?”

Поскольку оптимизатор Peep-дыр оптимизирует его, предварительно вычисляя результат такого умножения

 import dis dis.dis(compile("10 / float(98765)", "<string>", "eval")) 1 0 LOAD_CONST 0 (10) 3 LOAD_NAME 0 (float) 6 LOAD_CONST 1 (98765) 9 CALL_FUNCTION 1 12 BINARY_DIVIDE 13 RETURN_VALUE dis.dis(compile("10 / (98765 * 1.0)", "<string>", "eval")) 1 0 LOAD_CONST 0 (10) 3 LOAD_CONST 3 (98765.0) 6 BINARY_DIVIDE 7 RETURN_VALUE 

Он сохраняет результат 98765 * 1.0 в 98765 * 1.0 коде как постоянное значение. Таким образом, он просто должен загрузить его и разделить, где, как и в первом случае, мы должны вызвать функцию.

Мы можем видеть, что еще более отчетливо это

 print compile("10 / (98765 * 1.0)", "<string>", "eval").co_consts # (10, 98765, 1.0, 98765.0) 

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

Редактировать: Как отметил Давидм в комментариях ,

И причина, по которой он не оптимизирует разделение, заключается в том, что его поведение зависит от флагов, например, from __future__ import division а также из-за флага -Q .

Цитируя комментарий от фактического кода оптимизатора Peeon для Python 2.7.9 ,

  /* Cannot fold this operation statically since the result can depend on the run-time presence of the -Qnew flag */ 
  • Как __slots__ избегает поиска в словаре?
  • Почему python не использует __iadd__ для суммарных и цепочечных операторов?
  • Почему Python обрабатывает «1 1 ** 2» по-другому, чем «1000 - 10 ** 3»?
  • Определение того, является ли данный модуль Python встроенным модулем
  • Python: метод и дескрипторы __getattribute__
  • Python - лучший язык программирования в мире.