1

私が取り組んでいるメインコードに似た次のサンプルコードがあります。私が見た主なボトルネックは、call_fun の関数呼び出しにあります。これをスピードアップする方法はありますか?..例: 辞書オブジェクト self._d を使用せず、関数ルックアップに何か他のものを使用しますか? メイン コードでは、「名前」のリストはかなり大きいです。コードをすばやく理解するために、コメントアウトされた print ステートメントを有効にすることができます (... ただし、出力を印刷する場合は、範囲 (500000) 内の i を範囲 (1) 内の i に変更してください)

import time

names = [ ('f_a', ([1,1],)), ('f_b', ([3,4],) ) ]

class A(object):
    def __init__(self):        
        self._d = {}
        for n in names:            
            self._d[n[0]] = getattr(self, n[0])

    def call_fun(self, k):       
        #print " In call_fun: k: ", k
        return self._d[k[0]](*k[1])

    def f_a(self, vals):
        #print " I am here in f_a.. vals=", vals
        v =  2*vals
        return v

    def f_b(self, vals):
        v =  3*vals
        return v


# Run the code

start = time.clock()
a = A()
print "names[0]:", names[0]
for i in range(5000000):
    a.call_fun((names[0]))
print "done, elapsed wall clock time (win32) in seconds: " , time.clock() - start

プロファイリング出力は次のとおりです。python -m cProfile --sort cumulative foo.py

    10000009 function calls in 5.614 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    2.066    2.066    5.614    5.614 foo.py:1(<module>)
  5000000    2.345    0.000    3.412    0.000 foo.py:11(call_fun)
  5000000    1.067    0.000    1.067    0.000 foo.py:15(f_a)
        1    0.135    0.135    0.135    0.135 {range}
        1    0.000    0.000    0.000    0.000 foo.py:6(__init__)
        2    0.000    0.000    0.000    0.000 {time.clock}
        1    0.000    0.000    0.000    0.000 foo.py:5(A)
        2    0.000    0.000    0.000    0.000 {getattr}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
4

4 に答える 4

2

改善の余地はあまりないと思います。結局のところ、約 5 秒で 500 万回の関数呼び出しを行っていることになります。つまり、関数呼び出しごとに 2 GHz の CPU で 1µs (1ns ではありません) または約 2000 CPU サイクルに相当します。

その制限に耐えることができるなら、おそらくPyPyが最善の策です。

$ python -V
Python 2.7.1 
$ python so18736473.py
names[0]: ('f_a', ([1, 1],))
done, elapsed wall clock time (win32) in seconds:  5.418259
$ pypy -V
Python 2.7.2 (341e1e3821fff77db3bb5cdb7a4851626298c44e, Jun 09 2012, 14:24:11)
[PyPy 1.9.0]
$ pypy so18736473.py
names[0]: ('f_a', ([1, 1],))
done, elapsed wall clock time (win32) in seconds:  0.648846
于 2013-09-11T09:06:40.653 に答える