Я пытался оптимизировать программу, с которой я возился, когда заметил, что выполнение value = i % 65536
оказалось медленным, а затем value = i % (2**16)
.
Чтобы проверить это, я запустил следующую программу:
import cProfile
import pstats
AMOUNT = 100000000
def test1():
for i in xrange(AMOUNT):
value = i % 65536
return
def test2():
for i in xrange(AMOUNT):
value = i % (256**2)
return
def test3():
for i in xrange(AMOUNT):
value = i % (16**4)
return
def test4():
for i in xrange(AMOUNT):
value = i % (4**8)
return
def test5():
for i in xrange(AMOUNT):
value = i % (2**16)
return
def run_tests():
test1()
test2()
test3()
test4()
test5()
return
if __name__ == '__main__':
cProfile.run('run_tests()', 'results')
stats = pstats.Stats('results')
stats.sort_stats('calls', 'nfl')
stats.print_stats()
... который произвел следующий вывод:
Fri May 11 15:11:59 2012 results
8 function calls in 40.473 seconds
Ordered by: call count, name/file/line
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1 0.000 0.000 40.473 40.473 <string>:1(<module>)
1 0.000 0.000 40.473 40.473 test.py:31(run_tests)
1 10.466 10.466 10.466 10.466 test.py:6(test1)
1 7.475 7.475 7.475 7.475 test.py:11(test2)
1 7.485 7.485 7.485 7.485 test.py:16(test3)
1 7.539 7.539 7.539 7.539 test.py:21(test4)
1 7.508 7.508 7.508 7.508 test.py:26(test5)
Использование 65536
было самым медленным на 10.466 секунд, тогда как 256**2
было самым быстрым на 7,475 секунды (с другими возможными значениями экспоненты, находящимися между ними). Разумеется, эта разница в скорости заметна только при большом количестве повторений, но мне все еще интересно, почему это происходит.
Почему количество мод на 65536
медленнее, чем при использовании мода, используя экспоненты? Они должны оценивать один и тот же номер, и я бы подумал, что интерпретатору python потребуется больше времени, чтобы полностью оценить экспоненты, прежде чем принимать мода.
Как правило, более эффективно использовать полномочия двух в выражениях python, а не полностью набирать номер? И этот шаблон справедлив для операций, кроме модуля или других чисел, кроме 2
?
(Кстати, я использую Python 2.7.2 (32 бит), и я запустил выше на 64-битном ноутбуке Windows 7).
EDIT:
Поэтому я попытался изменить порядок функций, которые я называю, и теперь обратное верно. Похоже, что первая функция в run_tests
всегда будет работать медленнее при использовании cProfile, что странно. Итак, урок, я думаю, - профайлеры странны: D