Cでレジスタ変数を使用する良い例は何ですか?
-
10-07-2019 - |
質問
K& Rを読んでいて、レジスター変数の小さなセクションに来て、ここの人々がこれを実践する良い例があるかどうか疑問に思っていました。
K& Rのセクション4.7から:
レジスタ宣言は次のようになります
register int x;
register char c;
明確にするために、クールなコードサンプルをいくつか見たいと思っています。私は(私はかなり確信しているが)主題を理解しているので、(あなたが望んでいない限り)冗長な説明を入力する必要を感じないでください。
解決
最近のコンパイラーを使用する場合、レジスター使用法の良い例はありません(過去15年以上参照)。レジスタを使用すると、コンパイラに「あなたよりもコードを最適化する方法を知っています」と伝えています。これはほとんどありません。 registerを使用すると、次の3つのいずれかが発生します。
- コンパイラはそれを無視します。これはほとんどの場合です。この場合、唯一の害は、コードで変数のアドレスを取得できないことです。
- コンパイラはリクエストを受け入れ、その結果、コードの実行が遅くなります。
- コンパイラはリクエストを受け入れ、コードの実行速度が速くなります。これは最も可能性の低いシナリオです。
registerを使用すると、あるコンパイラがより良いコードを生成したとしても、別のコンパイラが同じことを行うと信じる理由はありません。コンパイラが十分に最適化していない重要なコードがある場合は、とにかくその部分にアセンブラを使用することをお勧めしますが、もちろん適切なプロファイリングを行って、生成されたコードが実際に問題であることを確認してください。
他のヒント
一般に、 Robert 、しかし良いルールとして、これには例外もあります。
深く埋め込まれたシステムで作業している場合、特定のハードウェアアーキテクチャ上の特定のアプリケーション向けにコードを最適化する方法をコンパイラよりもよく知っているかもしれません。
しかし、99%の場合、ロバーツの説明は埋め込み語にも適しています。
これはかなり前からのものであることがわかっていますが、少なくともgcc 4.5.2を使用してコードをコンパイルすることにより、レジスタ変数を使用するとアルゴリズムが高速化されるヒープソートのサブプロシージャの実装があります
inline void max_heapify(int *H, int i){
char OK = FALSE;
register int l, r, max, hI;
while(!OK){
OK = TRUE;
l = left(i);
r = right(i);
max = i;
if(l <= H[SIZE] && H[l] > H[i]){
max = l;
}
if(r <= H[SIZE] && H[r] > H[max]){
max = r;
}
if(max != i){
OK = FALSE;
hI = H[i];
H[i] = H[max];
H[max] = hI;
i = max;
}
}
}
属性の前にregisterキーワードを使用して、または使用せずにアルゴリズムをテストし、それを実行して、ノートブック上の50,000,000要素のランダム配列をバージョンごとに数回ソートしました。
レジスタの使用により、ヒープソート時間が〜135秒から〜125秒に短縮されました。
また、5,000,000個の要素のみでテストしましたが、実行回数を増やしました。
レジスタのないバージョンは11秒で開始しましたが、各実行は9,65秒に達するまで時間を短縮し、停止しました
レジスタのあるバージョンは10秒で開始し、8,80秒まで時間を短縮しました。
それはキャッシュメモリと関係があると思います。それにもかかわらず、レジスタは制約要因によってアルゴリズムを高速化するようです
これらの変数はアルゴリズムに沿って非常に多く使用されるため、この作業をコンパイラーに任せるのではなく、レジスター上にあることを確認することで、この場合の結果が改善されました。ただし、時間はそれほど改善されませんでした。
thillが誰かに役立つことを願っています、あいさつ。
別の一般的なケースは、低レベルのインタープリターを実装する場合です。レジスタに何らかの状態を保持する、例えば仮想マシンのスタックポインターは、メモリアクセスを大幅に削減し、コードを高速化できます。
vmgen& #8212;最適化の例については、効率的な仮想マシンインタープリターのジェネレーター(5.2スタックキャッシュのトップ)。
まず、レジスタ変数はループ制御変数などの頻繁に使用される変数に使用して、アクセス時間を最小限に抑えてパフォーマンスを向上させる必要があります。この状況でのみ使用でき、ストレージ指定子のみを登録できます like、fun(auto int a、auto int b):error fun(register int a、register int b):これだけが実行されます fun(静的int a、静的int b):エラー fun(extern int a、extern int b):エラー
まあこれは、C言語がアセンブリルーチンを呼び出すことができるため、高レベル言語の観点から、中レベルと低レベル(アセンブリまで)の複数のコーディングコンテキストがあるため、複数の回答が必要な質問です。
Cの代わりにアセンブリを使用する理由は、開発中にパフォーマンスの問題が発生するためです。sozはい、registerキーワードは必要ですが、多くの場合、開発者が意図したとおりに機能しません