64

私はちょうど気づいた

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で行うように、このような関数をインライン化することはできますか?

4

6 に答える 6

38

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

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

コメントに記載されているように、PyPyは自動的にインライン化されます(上記は引き続き有効です-実行時に最適化されたバージョンを「単に」生成し、その恩恵を受けますが、無効にされるとそれから抜け出します)が、この特定のケースでは役に立ちませんPyPyへのNumPyの実装はほんの少し前に開始され、今日までベータレベルではありません。しかし、肝心なのは、Pythonのこのレベルでの最適化について心配する必要はないということです。実装がそれ自体を最適化するか、最適化しないかのどちらかです。それはあなたの責任ではありません。

于 2011-06-22T15:31:48.203 に答える
28

OPが要求したものとは正確には異なりますが、閉じます。

インラインは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でのそのようなオプティマイザーの実装に伴う複雑さに興味がある人は、以下も確認することをお勧めします。

于 2016-10-26T11:53:03.930 に答える
10

このような最適化はCPythonに苦痛を与えるだけであり、パフォーマンスを気にする場合はPyPyを検討する必要があることに同意します(ただし、NumPyは不完全すぎて役に立たない場合があります)。ただし、PyPyでこのような最適化を気にすることはできますが、PyPyが自動的に行うと言われているような最適化ではありませんが、PyPyをよく知っている場合は、コードを調整してPyPyに必要なアセンブリを出力させることができます。ほぼこれまでに必要なことではありません。

于 2011-06-24T03:28:00.037 に答える
7

いいえ。

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

于 2011-06-22T15:09:11.873 に答える
7

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

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コードを書くための実際には生産的な方法ではありません。

于 2011-06-22T16:58:35.963 に答える
1

あなたは使用を試みることができますlambda

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

次に、次のように呼び出します。

y = abs2(x)
于 2019-06-24T13:38:21.923 に答える