23

そのため、使用しないという行を聞いたことがあるでしょregisterう。その理由は、コンパイラの最適化を超えようとするのはばかげた用事であるということです。

register、私が知っていることから、実際にはCPUレジスタについて何も述べていません。特定の変数を間接的に参照できないというだけです。コンパイラはアドレス指定の欠如を自動的に検出できるため、このような最適化を透過的にすることができるため、廃止されたと呼ばれることが多いと思います。

しかし、その議論に固執するなら、C のすべての最適化主導のキーワードに平準化することはできないのでしょうか? たとえば、なぜinlineC99 を使用するのでしょうか。restrict

エイリアシングのようなものによって、いくつかの最適化を推測するのが困難または不可能になると思います。

C および C++ では、コンパイラの最適化情報をスプーンでフィードすることと、コンパイラが何をしているのかを知っていると仮定することの間のどこに線を引く必要がありますか?

EDIT : Jens Gustedt は、私の C と C++ の混同は正しくないと指摘しました。これは、2 つのキーワードに意味上の違いがあり、1 つが標準の C++ に存在しないためです。C++に関する良いリンクがありregisterました。見つけたら追加します...

4

8 に答える 8

9

私はそれに同意しregisterinlineこの点で多少似ています。コンパイラが呼び出しサイトのコンパイル中に呼び出し先の本体を確認できる場合、インライン化について適切な決定を下すことができるはずです。C と C++ の両方でのキーワードの使用は、inline他の何よりも、関数の本体を可視化するメカニズムに関係しています。

restrictですが、違います。関数をコンパイルするとき、コンパイラは呼び出しサイトがどうなるかわかりません。エイリアシングがないと仮定できると、そうでなければ不可能な最適化が可能になります。

于 2013-04-12T11:48:18.077 に答える
5

register変数を間接的に参照できないとは言っていません (少なくとも C++ では)。元の C ではそうでしたが、それは削除されました。

コンパイラの最適化を超えようとすることがばかげた用事であるかどうかは、最適化に依存します。たとえば、多くのコンパイラsin(x) * sin(x) + cos(x) * cos(x)1.

現在、ほとんどのコンパイラは を無視registerしており、誰も使用していません。コンパイラは、レジスタの割り当てにおいて十分に優れているため、register. 実際、尊重registerすると、通常、生成されたコードが遅くなります。これはorの場合には当てはまりません: どちらの場合にも、少なくとも理論的には、コンパイラがあなたよりも良い仕事をする結果になる可能性のある手法が存在します。ただし、このような手法は普及しておらず、(少なくとも私の知る限り)コンパイル時間のオーバーヘッドが非常に高く、場合によっては、プログラムのサイズに応じてコンパイル時間が指数関数的に増加します (これにより、コンパイル時間が多かれ少なかれ大きくなります)。ほとんどの実際のプログラムでは使用できません—年単位で測定されるコンパイル時間は実際には受け入れられません)。inlinerestrict

どこで線引きをするかは… 時代によって変わります。私が最初に C でプログラミングを始めたときregister、大きな違いがあり、広く使用されていました。今日じゃない。inlineいずれ、 orについても同じことが起こる可能性があると想像しています。restrict一部の実験的なコンパイラは、inlineすでに or に非常に近いものになっています。

于 2013-04-12T11:56:11.600 に答える
5

inlineヘッダー内にテンプレート化されていない関数を実装し、それを複数のコンパイル ユニットから含めるシナリオで使用されます。

これにより、コンパイラはインライン化されているかのように関数のインスタンスを 1 つだけ作成する必要があるため、複数定義されたシンボルのリンク エラーは発生しません。ただし、コンパイラが実際にインライン化する必要はありません。

force-inline などと思われる GNU フラグがありますが、それは言語拡張です。

于 2013-04-12T11:49:00.000 に答える
5

これはおとりの質問ですが、とにかく飛び込みます。

コンパイラは、平均的なプログラマよりも最適化に優れています。25MHz の 68030 でプログラミングしたことがありregister、コンパイラのオプティマイザが非常に貧弱だったため、 を使用することである程度の利点が得られました。しかし、それは 1990 年のことです。

inlineと同じくらい悪いと思いますregister

一般に、変更する前に最初に測定します。registerコードのパフォーマンスが非常に悪く、 orを使用したい場合はinline、深呼吸をして、一歩下がって、まずより良いアルゴリズムを探してください。

最近 (つまり、過去 5 年間)、私はコード ベースをinline調べて、多くの関数を削除しましたが、目に見えるパフォーマンスの変化はありませんでした。ただし、コード サイズは、メソッドを削除することで常にメリットがありinlineます。これは、現代の標準的な x86 スタイルのモンスター マルチコア マーベルにとっては大きな問題ではありませんが、組み込みスペースで作業する場合は問題になります。

于 2013-04-12T11:58:17.747 に答える
2

違いは次のとおりです。

  • register非常に局所的な最適化です (つまり、1 つの関数内)。レジスタ割り当ては、よりスマートなコンパイラとより多くのレジスタの両方によって比較的解決された問題です (ほとんどが前者ですが、x86-64 には x86 よりも多くのレジスタがあり、両方とも 8 ビット プロセッサよりも多くの数があります)。
  • inline手順間の最適化であるため、より困難です。ただし、再帰の深さが比較的小さく、プロシージャの数が少ないため (インライン化されたプロシージャが大きすぎる場合は、インライン化する意味がありません)、安全にコンパイラに任せることができます。
  • restrictははるかに難しいです。2 つのポインターがエイリアスではないことを完全に知るには、プログラム全体 (ライブラリ、システム、プラグインなどを含む) を分析する必要があります。ただし、情報はプログラマーにとってより明確であり、仕様の一部です。

非常に単純なコードを考えてみましょう:

void my_memcpy(void *dst, const void *src, size_t size) {
    for (size_t i = 0; i < size; i++) {
        ((char *)dst)[i] = ((const char *)str)[i];
    }
}

このコードを効率的にする利点はありますか? はい -memcpy非常に便利な傾向があります (GC のコピーなど)。このコードはベクトル化できますか? コンパイラはそれを推測する必要がdstありsrc、エイリアスはまったくなく、それらが指す領域は独立しています。sizeユーザー入力、実行時の動作、または分析を実質的に不可能にするその他の要素に依存する可能性があります - 停止問題と同様の問題 - 一般に、実行せずにすべてを分析することはできません。または、Cライブラリ(共有ライブラリを想定)の一部であり、プログラムによって呼び出されるため、コンパイル時にすべての呼び出しサイトが認識されない場合もあります。このような分析がなければ、プログラムは最適化がオンになっていると異なる動作を示します。一方、プログラマーは、ボトムアップ分析を必要とせずに、(より高いレベルの) 設計を知るだけで、それらが異なるオブジェクトであることを確認できます。

restrict2 つのエイリアシング ポインターを処理できない方法でプロシージャを記述したのはプログラマである可能性があるため、ドキュメントの一部にすることもできます。たとえば、エイリアスの場所からメモリをコピーする場合、上記のコードは正しくありません。

要約すると、十分にスマートなコンパイラーは、プログラム全体を知らに (コードの意味を理解するコンパイラーに移動しない限り) を推測することはできません。それでも決定不能に近い。ただし、ローカル最適化については、コンパイラはすでに十分にスマートです。ただし、プログラム全体の分析を備えた十分にスマートなコンパイラーは、多くの興味深いケースで推測できると思います。restrict

PS。ローカルとは、単一の機能を意味します。したがって、ローカル最適化では、引数、グローバル変数などについて何も想定できません。

于 2013-04-12T19:54:29.543 に答える
2

コンパイラ テクノロジが向上しているため、これは移動中のターゲットです。(まあ、改善というよりは変化の方が多い場合もありますが、それは最適化の試みを意味のないものにしたり、さらに悪化させたりするのと同じ効果があります。)

一般に、最適化キーワードやその他の最適化手法が優れているかどうかを推測するべきではありません。対象とする特定のプラットフォームやコンパイラの仕組みなど、コンピューターの仕組みについてかなりのことを学ぶ必要があります。

したがって、さまざまな最適化手法を使用する際のルールは、コンパイラがここで最善の仕事をしないことを知っていますか? と尋ねることです。このコードが使用されている間、コンパイラは安定したままになりますか? コンパイラがこの状況を変えたときに、コードを書き直すつもりはありますか? 通常、コンパイラよりも優れた作業を行うには、経験豊富で知識のあるソフトウェア エンジニアである必要があります。また、コンパイラの開発者と話をすることも役に立ちます。

これは、人々がここで明確なガイドラインを持つ答えを与えることができないことを意味します. 使用しているコンパイラ、プロジェクト、リソース、目標などによって異なります。

コンパイラの最適化を超えようとするなと言う人もいますが、ソフトウェア エンジニアリングのさまざまな分野で、人々がコンパイラよりも優れたパフォーマンスを発揮し、そのために人にお金を払う価値があります。

于 2013-04-12T13:47:11.970 に答える
2

言及されていないことの 1 つは、多くの非 x86 コンパイラはgcc、他の "最新の" C コンパイラほど最適化が得意ではないということです。

たとえば、PIC のコンパイラは最適化がまったく苦手です。また、( CUDAコンパイラー)のオプティマイザーは、はるかに優れていますが、かなり単純な最適化の多くを見逃しているようです。cicc

registerこれらのケースでは、 、inline、 などの最適化のヒント#pragma unrollが非常に役立つことがわかりました。

于 2013-04-12T16:58:46.840 に答える