Pythonの四則演算とビット論理演算の速度

python2.5で整数に対する基本的な演算の速度を測って見ました。

環境は

計測したのは四則演算と剰余、論理積論理和排他的論理和の8つです。
それぞれの計算では変数i,jを1から2047までループして演算し全体の時間を計測し、2047^2で割って一回あたりの演算時間としました。下がその結果です。意外な事に、ビット演算の速度が遅いです。

$ py func_call_time.py | tee out
op	all[sec]	per call[sec]
------------------------------------------------------------
add	5.524e-01	1.318e-07
sub	5.459e-01	1.303e-07
mul	7.791e-01	1.859e-07
div	7.774e-01	1.855e-07
mod	7.749e-01	1.849e-07
logand	7.298e-01	1.742e-07
logor	7.457e-01	1.780e-07
logxor	7.736e-01	1.846e-07

予想は

  • logand, logor < logxor < add, sub < mul, div < mod

でしたが、実際には

  • sub,add < logand, logor < logxor, mod, div, mul

でした。

(ソートしたもの)
sub     5.459e-01       1.303e-07
add     5.524e-01       1.318e-07
logand  7.298e-01       1.742e-07
logor   7.457e-01       1.780e-07
logxor  7.736e-01       1.846e-07
mod     7.749e-01       1.849e-07
div     7.774e-01       1.855e-07
mul     7.791e-01       1.859e-07

どうやらPython2.5.1では高速化のためのビット論理演算は効果が薄いようです。

以下ソースコードです。

#! /bin/env python
# coding: utf-8
# func_call_time.py
# 四則演算の速度がCと似ているかどうか確かめるコード.
# *Cと同じ... |,&,+,- > *,/ > %

from time import time
# 定義
names = ["add", "sub", "mul", "div", "mod",
         "logand", "logor", "logxor"]
ops = ["+", "-", "*", "/", "%",
       "&", "|", "^"]
def template(name, op):
    return """def %s():
    for i in xrange(1,2048):
        for j in xrange(1,2048):
            i %s j
""" % (name, op)

for pair in zip(names, ops):
    exec template(*pair)

    
# 呼び出し
def calltime(func_name):
    start = time()
    exec func_name+"()"
    end = time()
    return end - start


times = [calltime(n) for n in names]
format = "%s\t%.3e\t%.3e"
print "op\tall[sec]\tper call[sec]"
print "-"*60
print "\n".join(format % (pair[0], pair[1], pair[1]/2047**2) for pair in zip(names, times))