2016-08-08 3 views
0

Я пытаюсь проверить улучшение скорости использования JIT в python. Вот код, который я использую.Невозможное ускорение при использовании JIT в python. Что происходит?

from numba import jit 
import timeit 

@jit # Commented out when testing pure python 
def sumof(): 
    x = 0 
    for i in xrange(1000000000): 
     x += 1 
    return x 

def timer(): 
    sumof() # Run once to initialize the JIT compiler 
    l = [] 
    t = timeit.default_timer() 
    for x in range(10): 
     l.append(sumof()) 
    return timeit.default_timer()-t, l # Returns the time elapsed and the list of results, to verify accuracy 

print timer() 

Это дает результат, аналогичное этому

(5.643910299113486e-06, [1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 1000000000, 1000000000]) 

Теперь я знаю, что сырая производительность процессора на несколько порядков быстрее, чем чистый питон, но 10 миллиардов операций в 5 микросекундах ?? Я тестировал этот же код, но использовал максимальное значение подписанного 64-битного целого, а не миллиарда. В результате.

(5.643909389618784e-06, [9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L, 9223372036854775807L]) 

~ 92 квадриллиона операций ... в 5 микросекунд. По моей математике, это около 16 сегментов операций в секунду. Что-то явно не так, но оно дает правильный результат. Я подозреваю, что компилятор каким-то образом избавляется от цикла for, но почему? И как я могу это предотвратить?

+0

'for i in xrange (1000000000): x + = 1' - очень простой цикл (упрощается до 1000000000), возможно, машинный код полностью оптимизирует его. – 101

+1

Умм, разве это не результат вашего теста? По крайней мере, в этом случае коэффициент ускорения при использовании джитта numba действительно составляет 10^8. – phihag

+0

@ 101 Это также происходит, когда я заменяю функцию общей функцией «умножение на повторное добавление». Если цикл заменяется на 'for i в xrange (a): x + = b'. Я согласен с вами в том, что это простой цикл, и я вижу, как компилятор выбрасывает тот, что есть в моем вопросе, но компиляторы действительно так волшебны, чтобы это сделать? – Daffy

ответ

1

Похоже, что оптимизатор заменил цикл на один постоянный расчет. См. https://en.wikipedia.org/wiki/Loop_optimization для списка классических оптимизаций цикла. В этом случае, полностью разворачивая цикл, а затем объединяя все константы, получается return n (с x + = 1) или return n * b (с x + = b). Использование x += i результатов в return n * (n + 1)/2. (В каждом случае n является соответствующая верхняя петля связана:. При подведении i в range(n), это действительно просто n-1 вместо этого)

Поскольку это JIT компилятор, он может сделать это, даже для переменной n, хотя в ваших примерах каждый n является константой, поэтому даже компиляторы, не относящиеся к JIT, могут это сделать.

+1

Ну, черт, компиляторы просто умнее, чем я думал. – Daffy

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