Скорость расчета мощности (в питоне)

Если вы используете функцию Джерси 2.x, используйте следующую зависимость:


   org.glassfish.jersey.containers
   jersey-container-servlet-core
   2.XX
  

Где XX может быть любая конкретная версия, которую вы ищете. Контейнеры Джерси .

30
задан Christwo 19 June 2009 в 20:20
поделиться

5 ответов

В основном простое умножение - это O (n) с очень низким постоянным коэффициентом. Взятие мощности - это O (log n) с более высоким постоянным коэффициентом (есть особые случаи, которые необходимо проверить ... дробные показатели, отрицательные показатели и т. Д.). Изменить: просто для ясности, это O (n), где n - показатель степени.

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

24
ответ дан 28 November 2019 в 00:13
поделиться

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

Это зависит от конкретной реализации, если этот вид деталей не определен языком.

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

7
ответ дан 28 November 2019 в 00:13
поделиться

Я подозреваю что никто не ожидал, что это будет настолько важным. Обычно, если вы хотите провести серьезные вычисления, вы делаете их в Fortran, C или C ++ или что-то в этом роде (и, возможно, вызываете их из Python).

Обработка всего как exp (n * log (x)) хорошо работает в случаи, когда n не является целым или довольно большим, но относительно неэффективным для небольших целых чисел. Проверка того, является ли n достаточно малым целым числом, требует времени и добавляет сложности.

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

1
ответ дан 28 November 2019 в 00:13
поделиться

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

Вот быстрое доказательство концепции, которая выполняет такую ​​оптимизацию (может использоваться в качестве декоратора). Примечание. Для его запуска вам понадобится модуль byteplay .

import byteplay, timeit

def optimise(func):
    c = byteplay.Code.from_code(func.func_code)
    prev=None
    for i, (op, arg) in enumerate(c.code):
        if op == byteplay.BINARY_POWER:
            if c.code[i-1] == (byteplay.LOAD_CONST, 2):
                c.code[i-1] = (byteplay.DUP_TOP, None)
                c.code[i] = (byteplay.BINARY_MULTIPLY, None)
    func.func_code = c.to_code()
    return func

def square(x):
    return x**2

print "Unoptimised :", timeit.Timer('square(10)','from __main__ import square').timeit(10000000)
square = optimise(square)
print "Optimised   :", timeit.Timer('square(10)','from __main__ import square').timeit(10000000)

Что дает время:

Unoptimised : 6.42024898529
Optimised   : 4.52667593956

[Изменить] На самом деле, если подумать еще немного, есть очень веская причина, по которой эта оптимизация не выполнена. Нет никакой гарантии, что кто-то не создаст определенный пользователем класс, который переопределяет методы __ mul __ и __ pow __ и будет делать что-то свое для каждого из них. Единственный способ сделать это безопасно - это гарантировать, что объект на вершине стека имеет одинаковый результат «x ** 2 » и « x * x ] ", но решить это намного сложнее. Например. в моем примере это невозможно, так как любой объект можно передать функции square.

4
ответ дан 28 November 2019 в 00:13
поделиться

как насчет x x x x x? это все еще быстрее, чем x ** 5?

по мере того, как показатели int становятся больше, получение степеней может быть быстрее, чем умножение. но количество фактических кроссоверов зависит от различных условий, поэтому, на мой взгляд, именно поэтому оптимизация не была сделана (или не могла быть проведена) на уровне языка / библиотеки. Но пользователи все еще могут оптимизировать для некоторых особых случаев :)

0
ответ дан 28 November 2019 в 00:13
поделиться
Другие вопросы по тегам:

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