質問

私の機能は、何千回と呼ばれます。私はそれを速くしたい場合は、任意の使用の静的であるとローカル関数変数を変更するのだろうか?この背後にある私のロジックは、静的変数は、関数呼び出しの間で永続的であるため、彼らは唯一の最初の時間が割り当てられ、これにより、すべての後続の呼び出しは、彼らのためにメモリを割り当てないであろうと、メモリ割り当てステップが行われていないので、速くなります、それです。

上記が真である場合は、

また、その後、使用して、グローバル変数の代わりに、パラメータが関数にそれが呼び出されるたびに情報を渡すために速くなるでしょうか?パラメータのためのスペースも(再帰がより多くのメモリを使用しています理由です)再帰を可能にするために、すべての関数呼び出しに割り当てられたが、私の関数は再帰的ではないので、そして私の推理が正しければ、その理論メイクのパラメータをします離陸される私だと思いますそれより速くます。

私は恐ろしいプログラミングの習慣ですやりたいこれらの事を知っているが、それは賢明であれば、教えてください。私はとにかくそれをしようが、私にあなたの意見をお願いしようと思ってます。

役に立ちましたか?

解決

ローカル変数のオーバーヘッドはゼロです。関数を呼び出すたびに、あなたはすでにあなたがスタックポインタ(コンパイル時に計算された数)に大きめの数を追加していることを、ローカル変数の手段を追加するなど、パラメータの戻り値をスタックに設定していますます。

また、ローカル変数は、おそらく速くキャッシュの局所性に起因するものです。

のプロファイラを実行した後、あなたは唯一のは、あなたは、最適化の機会をあなたのアルゴリズムを見てする必要があり、時間(ない何百万あるいは数十億)のあなたの機能「数千人」と呼んでいる場合。

<時間>

日時:キャッシュの局所性( をもっとここで読みます): 頻繁にアクセスされるグローバル変数は、おそらく時間的局所性を持っています。彼らはまた、機能の実行中にレジスタにコピーすることができるが、関数が返す(そうでない場合は、何か他のものにアクセスできません。レジスタはアドレスを持っていない)の後に戻っメモリ(キャッシュ)に書き込まれます。

ローカル変数は、一般的に(彼らはスタック上に作成されるのおかげでそれを得る)、時間と空間の両方の局所性を持つことになります。さらに、彼らは、レジスタに直接「割り当てられた」とすることができるメモリに書き込まれることはありません。

他のヒント

を見つけるための最善の方法は、実際にプロファイラを実行することです。これは、両方の方法を使用して、いくつかの時限テストを実行し、結果を平均と比較するような単純なようであることができるか、時間と実行速度を超えるメモリ使用アウト処理やグラフに付着本格的プロファイリングツールを考慮することができます。

あなたはそれがより速くなるでしょう。直感を持っているので、

はランダムなマイクロコードチューニングを実行しないでください。コンパイラは、すべての他の構成上の偽かもしれ若干異なるものの実装やどのような1つの環境上の1つのコンパイラに真であるがあります。

少ないパラメータについてそのコメントに取り組むために:「インライン化」機能のプロセスは、本質的に関数を呼び出すに関連するオーバーヘッドを削除します。チャンスは小さな関数は、コンパイラによって並んで、自動的になりますが、することができます<のhref =「http://www.greenend.org.uk/rjk/2003/03/inline.html」のrel =「noreferrer」 >機能を提案するだけでなくをインライン化する。

異なる言語、C ++、新しい標準サポートを出て、完璧な転送、および関数を呼び出すのコストを減らすことができます特定のケースでの一時が不要に右辺値参照を持つ完璧な動きの意味で

あなたがあなたの本当のボトルネックを発見したまで、私はあなたが途中で最適化している疑いがある、しかし、あなたはこのパフォーマンスに関わるべきではありません。

Absolutlyありません!変数が初期化

あるときにのみ、「パフォーマンス」の違いは、
    int anint = 42;
 vs
    static int anint = 42;

最初のケースでは、整数は42に機能プログラムがロードされたときに42に設定されるOT第二の場合に呼び出されるたびに設定されます。

はしかし差はほとんど顕著であるほど自明です。ストレージは、すべての呼び出しで「自動」変数に割り当てられる必要があること、その一般的な誤解。 Cは、これらの変数にスタックにすでに割り当てられたスペースを使用していますので、これではありません。

そのいくつかのアグレッシブ最適化は、静的変数にはできませんとして

静的変数は、実際にあなたが遅くなる場合があります。地元の人々は、スタックの連続した領域にあるとしても、それらは効率的にキャッシュに簡単です。

これに誰も答えはありません。あなたが関数を呼び出し、そして恐らく月の段階までには、CPUのは、やって何CPU、コンパイラ、コンパイラフラグ、あなたが持っているローカル変数の数によって変化します。

両極端を考えます。あなたが唯一の1つまたは少数のローカル変数を持っている場合、それ/それらを簡単にレジスタに格納されるかもしれないのではなく、すべてのメモリ位置を割り当てられます。レジスタ「圧力」はまったく命令を実行せずにこれが起こることが十分に低い場合ます。

反対の極端では、すべてのスタックを持っていないいくつかのマシン(例えば、IBMのメインフレーム)があります。この場合、私たちは通常、スタックフレームが実際にヒープ上のリンクリストとして割り当てられていると考えるだろう。あなたはおそらく推測するだろうとして、これをすることができ、のかなりの遅います。

それが変数にアクセスすることになると、

は、状況はやや似ています - マシン・レジスタへのアクセスはかなりよく高速なメモリに割り当てられた何よりもあることが保証されてできるための可能な希望。 OTOH、それはかなり遅いことがスタック上の変数にアクセスすることは可能だ - それは、通常はかなり遅くなる傾向がある(特に古いCPUを搭載した)インデックス付き間接アクセス、のようなものが必要です。 OTOH、グローバル(静的は、その名がグローバルに表示されていないにも関わらず、である)へのアクセスは、典型的にもある程度いくつかのCPU PENALIZE絶対アドレスを形成する必要があります。

ボトムライン:あなたのコードをプロファイリングするにもアドバイスが紛失することができる - の違いはあっても容易プロファイラがdependablyそれを検出しないように小さなであってもよく、確かにののみの方法生産されますアセンブリ言語を調べて(と言うのは何もあなたのの行いがのそれを見て知っているだけでなく、十分なアセンブリ言語を学ぶ数年を過ごす)することです。この他の側面は、あなたが違いを扱っているときにも、dependably測定することができないこと、それは実際のコードの速度に重要な影響を持っているだろうという可能性は非常にリモートそれはおそらくトラブル価値はないということです。

それは非静的対静的が完全にカバーされているようですが、グローバル変数の話題になります。多くの場合、これらは、それをプログラムの実行ではなく、スピードをアップ遅くなります。

<のp>その理由は、コンパイラがすべてのグローバルは、その最適化が良いようではありません、その後に使用される可能性がありますどこのインスタンスのアプリケーションに目を通す必要がある場合しっかりとスコープの変数は、重く最適化するために、コンパイラのために簡単にそれを作ることです。

:あなたは、ポインタを紹介したときに

このは配合されて、次のコードを持っていると言います

int myFunction()
{
    SomeStruct *A, *B;
    FillOutSomeStruct(B);
    memcpy(A, B, sizeof(A);
    return A.result;
}

コンパイラは、ポインタAとBは決してオーバーラップし、それがコピーを最適化することができるようにすることができますことを知っています。 AとBがグローバルである場合、それらはおそらくメモリの重複にまたは同一指すことができ、この手段は、コンパイラが遅くなる「それは安全なプレイ」しなければなりません。問題は、一般に「ポインタのエイリアス」と呼ばれ、状況だけでなく、メモリコピーのロットで発生する可能性があります。

http://en.wikipedia.org/wiki/Pointer_aliasする

はい、静的変数を使用すると、ほんの少し速く機能を行います。あなたがあなたのプログラムがマルチスレッドにしたい場合は、この問題が発生します。静的変数は、異なるスレッドで同時に関数を呼び出し、関数呼び出しの間で共有されるので、未定義の動作になります。マルチスレッドは、あなたが本当にあなたのコードをスピードアップするために、将来的にやりたいことが事のタイプです。

はあなたが言及したものの大部分は、マイクロ最適化と呼ばれています。一般的に、物事のこれらの種類を心配することは悪い考えです。それはあなたのコードが難しく読みになり、そして維持が困難になっています。また、バグを導入する可能性が高いです。あなたはおそらくあなたの降圧がより高いレベルで最適化を行うためのより多くの強打を取得します。

M2tMの提案として、プロファイラを実行していることも良いアイデアです。非常に使いやすいです1は、 gprofのにチェックしてくださいます。

あなたはいつも本当に最速であるかを判断するようにアプリケーションを時間を計ることができます。ここで私が理解である:(このすべてが、ところで、あなたのプロセッサのアーキテクチャに依存します)。

C関数は、渡されたパラメータが置かれている場所であるスタックフレームを作成し、ローカル変数が置かれ、並びに発呼者が関数と呼ばれる場所への復帰ポインタバック。ここにはメモリ管理の割り当てはありません。これは通常、単純なポインタの動きと、それのthats。スタックからデータにアクセスすることもかなり速いです。あなたはしているが、ポインタを扱うときに罰則は通常、遊びに来ています。

グローバルまたは静的変数については、それらは同じだ...立場から、彼らはメモリの同じ領域に割り当てられることになるだろうということ。これらは、ローカル変数よりもアクセスの異なる方法を使用してアクセスすると、コンパイラに依存します。

あなたのシナリオの主な違いは、メモリフットプリントで、それほどスピードます。

実際に大幅にあなたのコードを作ることができ、静的変数を使用して、の遅くの。静的変数は、メモリの「データ」領域に存在しなければなりません。その変数を使用するために、機能は、メインメモリ、またはそれに書き込むストア命令から読み取るためのロード命令を実行しなければなりません。その領域がキャッシュにない場合、あなたは多くのサイクルを失います。スタック上の生命は、最も確実に全てのメモリに登場することはありません、キャッシュ内にあり、さらに、CPUのレジスタであるかもしれないアドレスを持つことをローカル変数ます。

私はそのようなものを見つけるためにプロファイリングが、一般的に関数の静的変数が遅くする必要があり、話すについて他の人のコメントに同意します。あなたがそれらをしたい場合は、あなたが本当に後にしていることは世界的です。事はあなたの関数が呼び出されるたびに実行されることをすでに初期化されている場合。

コード/データ挿入機能静チェックします

プロファイリングを解体し、かもしれない何を探すべきかを知って、違いが表示されないことがあります。

私はあなただけ(など、平均的にコンパイラに依存)ループあたり数クロックサイクル限り変動を得ようとしている疑いがあります。時々変更は変数ホームがスタックから/に移動したため、必然的になり、劇的な改善または劇的に遅く、その文句を言わないだろう。あなたは2GHzのプロセッサ上の10000回のコールのための関数呼び出しごとに4つのクロックサイクルを節約言うことができます。非常に粗い計算:保存された20マイクロ秒。あなたの現在の実行時に比べて20マイクロロットまたは少しですか?

あなたはおそらく他のものの間で、int型にあなたのcharと短い変数のすべてを行うことによって、よりパフォーマンスの向上を取得します。マイクロ最適化は、知っていることは良いことですが、少数の命令は、必ずしも例えば速く意味しないことを理解し、あなたのコードの実行タイミング、解体、実験多くの時間を要します。

特定のプログラム、分解したり、当該機能と、それを呼び出すコードの両方を取ります。し、静的なし。あなたが1つまたは2つの命令を獲得し、これはあなたがやろうとしている唯一の最適化である場合、それはおそらく、それだけの価値はありません。あなたは、プロファイリングしながら、違いを見ることができない場合があります。キャッシュラインは、例えばコードの変更前のプロファイリングに表示でき打つ場所の変更ます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top