5

私は(平均して)10000回以上呼び出される5つの関数を持っています。それらはすべて、特定の変数を変更/使用します。

グローバル変数を持つのは悪い習慣だと私は知っています。しかし、パフォーマンスのために、それらをグローバルに保ち、それらを渡さないことは理にかなっています-特に私がこれらを何度も関数呼び出しをしているときは?

または、パフォーマンスの面であまり利益を得るつもりはありませんか?

4

7 に答える 7

7

パフォーマンスの目的でグローバル変数/グローバル状態を導入しないでください。これは、すべての優れたコーディング手法とは異なり、誤った方向に進んでおり、通常はパフォーマンスに役立ちません(害を及ぼす可能性さえあります)。

たくさんの変数を渡すのにコストがかかりすぎると感じた場合は、それらすべてをコンテキストに入れてstruct、単一のポインターをに渡すことができますstructstaticこのようにして、コードが複数のインスタンスで使用できなくなるグローバル状態(ストレージ期間変数もグローバル状態)の作成を回避できます。コストは実質的にゼロであり、実際には、位置に依存しないコード(共有ライブラリまたは位置に依存しない実行可能ファイル)のグローバル変数よりもコストが低くなります。

于 2011-07-14T00:19:54.857 に答える
5

変数(グローバル変数や静的変数など)を事前に割り当てることで、関数に渡されるパラメーターの数を減らすことで、パフォーマンスがわずかに向上する場合があります。

パフォーマンスの変化は、開発しているプラ​​ットフォームだけでなく、多くのことに完全に依存します。小さなマイクロプロセッサ用に開発している場合、(呼び出し元の関数から)スタックにパラメータをコピーするのにかかる時間とスタックにアクセスするのにかかる時間は、それを保証するのに十分な合計実行時間の割合になる可能性があります。

パラメータの受け渡しに時間がかかる状況では、他のいくつかの提案(たとえば、構造体へのポインタの受け渡し、静的変数へのポインタの受け渡し)も何のメリットももたらさないことに注意してください。グローバル変数を使用すると、コンパイラ/リンカは、スタック上のポインタから間接的に変数にアクセスするのではなく、それらの変数にハードコードでアクセスできるようになります。これは、キャッシュを持たないプロセッサに特に関係があります。

もちろん、これはすべてターゲットに大きく依存し、使用しているプロセッサの命令セットに大きく依存します。妥当な命令セットを備えたプラットフォームでは、改善が見られるはずです。

ただし、このような対策は、このコードをプロファイリングした後にのみ実行する必要があります。ほとんどのプラットフォームでは、重要な関数を使用して、パラメーターを渡してそれらにアクセスするのにかかる時間は重要ではありません。潜在的なパフォーマンスの向上は、コードの保守がより困難になるという犠牲を払ってもたらされます。

他の最適化手法を使用することで、パフォーマンスが大幅に向上する可能性が非常に高くなります。試す方法については、この質問を確認してください。


編集:あなたのコメントの1つから、あなたはまだこのプロジェクトの設計段階にあることがわかります。

このような最適化を行うには、プロセスの初期段階です。この段階では、このような命令レベルで最小化するよりも、使用するアルゴリズムを最適化することで、パフォーマンスにはるかに大きな影響を与えることになります。

于 2011-07-14T01:02:03.543 に答える
3

静的変数はCにファイルスコープがあり、関数を1つのファイルにグループ化できる場合は、それらで十分な場合があります。そして私にとって、静的変数はグローバル変数よりも数桁問題が少ないです。

見過ごされがちな問題の1つは、関数本体内で宣言された変数がスタックに割り当てられるのに対し、静的変数は通常、bssと呼ばれる制限の少ないメモリプールから割り当てられることです。したがって、関数内ですべての変数を適切に定義すると、スタックの枯渇の問題が発生する可能性があり、静的変数を使用すると非常にクリーンな方法で回避できます。

于 2011-07-14T00:11:14.580 に答える
2

私は、グローバル変数はおそらくパラメーターを渡すよりも遅くなるだろうと言っているところまで行きます。パラメータは、頻繁に使用されるスタック上に存在するため、キャッシュ内にある可能性があります。グローバル変数は静的空間に存在します。静的空間は使用量がはるかに少ないため、キャッシュ内に存在する可能性が低くなり、メモリルックアップが大幅に遅くなります。キャッシングの考慮事項により、(新しい関数への)ジャンプは、関数呼び出し操作全体の中で最も遅い部分である可能性があります。

関数が小さい場合は、それらをインライン化することを検討してください。それらが大きい場合、スタックに1つまたは2つの単語をプッシュしても、違いは最小限になる可能性があります。

また、パラメーターの受け渡しにスタックを使用することは、非常にx86であることに注意してください。多数のレジスタを備えたARMおよびその他のアーキテクチャは、通常、非常に高速なパラメータの受け渡しにいくつかのレジスタを使用します。

于 2011-07-14T00:23:39.837 に答える
2

一部の組み込みマイクロコントローラーでは、パラメーターの代わりにグローバル変数を使用することでパフォーマンス上の利点が得られる場合がありますが、これはマシンに大きく依存します。

たとえば、一般的な8ビットマイクロコントローラコンパイラ(HT-PICC18)を使用する場合、グローバル変数を設定するコストは、1バイトあたり2命令/2サイクルです。1バイトのパラメータを渡すには、命令/1サイクルのコストがかかります。2バイト以上のパラメーターを渡すには、1バイトあたり2サイクルかかります。したがって、2つのシングルバイトパラメータを渡す最も効率的な方法は、1つをパラメータとして渡し、もう1つをグローバルとして渡すことです。

68HC11のIntrolコンパイラでは、自動変数またはパラメータを持つルーチンには、複数の命令のプロローグとエピローグが必要です。これらは、すべての変数が静的で、パラメータがグローバルとして渡される場合は省略できます。ただし、ルーチンがローカルまたはパラメーターを使用する場合、他のすべてにローカルおよびパラメーターを使用する場合の限界費用はごくわずかです。

ARMでは、キャッシュがない場合でも、逆の状況がしばしば当てはまります。自動変数またはパラメーターへのアクセスは、グローバル変数へのアクセスよりも高速であることがよくあります。自動変数とパラメーターはレジスターにあるか、レジスターに保管されているアドレスから直接アクセスできる既知のオフセットにあります。対照的に、グローバル変数へのアクセスは、多くの場合2段階のプロセスになります。最初にグローバル変数のアドレスをロードしてから、変数自体にアクセスします。

于 2012-02-09T16:18:08.760 に答える
1

人々は一般に、本当に必要でない限り(つまり、何かが本当にグローバルな状態を持っている場合を除いて)、グローバルパラメータから離れようとします。特にマルチスレッドアプリケーションの場合、グローバルパラメータを使用すると必要以上に困難になる可能性があります。

パフォーマンスに関しては、信じがたいことですが、グローバル変数へのアクセスが高速になる場合があると示唆する人もいます、確実にする唯一の方法は、特定のケースに対して実際にベンチマークを実行することです。

個人的に、私はこれを決してしません。パラメーターが関数に渡される方法を考え(たとえば、大きなデータ型の場合、コピーではなくポインターによって渡されることを確認してください)、正しい(最良の)最適化設定がに渡されるようにしますコンパイラ。

お役に立てれば。

于 2011-07-14T00:22:50.957 に答える
0

パラメータをグローバル変数に置き換えてもパフォーマンスは向上しないと思います。

とにかく、これを実行したい場合は、同じファイル内のすべての関数と変数を宣言し、変数を静的として宣言することも検討できます。このようにして、同じファイルで宣言された関数のみがそれらにアクセスできます。

こちらをご覧ください

于 2011-07-14T00:12:35.887 に答える