web-dev-qa-db-ja.com

Pythonインライン関数またはマクロと同等

私はちょうどそれを実現しました

x.real*x.real+x.imag*x.imag

行うよりも3倍速い

abs(x)**2

ここで、xは複素数のnumpy配列です。コードを読みやすくするために、次のような関数を定義できます

def abs2(x):
    return x.real*x.real+x.imag*x.imag

これはまだabs(x)** 2よりはるかに高速ですが、関数呼び出しの代価がかかります。マクロやインラインキーワードを使用してCで行うように、そのような関数をインライン化することは可能ですか?

46
Charles Brunet

マクロやインラインキーワードを使用してCで行うように、そのような関数をインライン化することは可能ですか?

いいえ。この特定の命令に到達する前に、Pythonインタープリターはそのような関数があるかどうかさえ知らず、それが何をするかはほとんどわかりません。

コメントで述べたように、PyPy 自動的にインライン化されます(上記は引き続き有効です-実行時に最適化されたバージョンを「単純に」生成し、それから利益を得ますが、無効になったときにブレークアウトします) NumPyをPyPyに実装するのに役に立たない特定のケースは、ほんの少し前に始まったばかりで、今日までベータレベルではありません。しかし、肝心なのは、Pythonのこのレベルでの最適化については心配しないでください。実装自体が最適化するか、最適化しないかは、あなたの責任ではありません。

33
user395760

OPが要求したとおりではありませんが、近いです:

Inliner inlines Python関数呼び出し。 このブログ記事 の概念実証

from inliner import inline

@inline
def add_stuff(x, y):
    return x + y

def add_lots_of_numbers():
    results = []
    for i in xrange(10):
         results.append(add_stuff(i, i+1))

上記のコードでは、add_lots_of_numbers関数は次のように変換されます。

def add_lots_of_numbers():
    results = []
    for i in xrange(10):
         results.append(i + i + 1)

また、この質問に興味がある人や、CPythonでそのようなオプティマイザーを実装するのに伴う複雑な問題については、以下も参照してください。

13
AXO

私は他の皆にそのような最適化があなたに痛みを引き起こすだけであることに同意しますCPythonで、パフォーマンスを気にするならPyPyを考慮する必要があります(NumPyは不完全すぎて役に立たないかもしれませんが)。しかし、PyPyの自動最適化についてはこれまで述べてきたようなものではなく、PyPyの最適化については気にすることができるとは言いませんが、PyPyをよく知っているなら、本当にあなたのコードを調整してPyPyが望むアセンブリを出力できるようにします、ほぼ必要なわけではありません。

7
Alex Gaynor

実際には、次のように計算がさらに高速になる場合があります。

x.real** 2+ x.imag** 2

したがって、関数呼び出しの追加コストは減少する可能性があります。どれどれ:

In []: n= 1e4
In []: x= randn(n, 1)+ 1j* Rand(n, 1)
In []: %timeit x.real* x.real+ x.imag* x.imag
10000 loops, best of 3: 100 us per loop
In []: %timeit x.real** 2+ x.imag** 2
10000 loops, best of 3: 77.9 us per loop

そして、計算を関数にカプセル化する:

In []: def abs2(x):
   ..:     return x.real** 2+ x.imag** 2
   ..: 
In []: %timeit abs2(x)
10000 loops, best of 3: 80.1 us per loop

とにかく(他の人が指摘したように)この種のマイクロ最適化(関数呼び出しを避けるため)は、python code。

6
eat

番号。

Cマクロに最も近いのは、メイクファイルに含めることができるスクリプト(awkまたはその他)であり、pythonでabs(x)** 2のような特定のパターンを置き換えます長い形式のスクリプト。

6
Thaddee Tyl

lambdaを使用してみてください:

abs2 = lambda x : x.real*x.real+x.imag*x.imag

次に呼び出します:

y = abs2(x)
1
Linfeng Mu