純粋関数のGCC最適化

ルー

GCCがpure関数の最適化について保証していることに混乱しています(オンラインドキュメントから):

pure

多くの関数は、戻り値を除いて効果がなく、その戻り値はパラメーターやグローバル変数のみに依存します。(...)

興味深い非純粋関数は、無限ループを持つ関数、または揮発性メモリやその他のシステムリソースに依存する関数であり、2つの連続する呼び出し間で変更される可能性があります(feofマルチスレッド環境など)。

そしてのためにconst

const

多くの関数は、引数以外の値を調べず、戻り値以外の効果はありません。基本的に、これは、関数がグローバルメモリを読み取ることを許可されていないため、以下の純粋な属性よりもわずかに厳密なクラスです。

ポインタ引数を持ち、ポイントされたデータを検査する関数は宣言してはならないことに注意してくださいconst同様に、非const関数を呼び出す関数は、通常constであってはなりません。

そこで、ポインタパラメータを受け入れる関数を作成して、マークを付けてみましたpureしかし、私はオンラインGCCを使用してこの機能をコンパイルしようとした(私は両方を試してみましたconstpure):

typedef struct
{
    int32_t start;
    int32_t end;
}
Buffer;

inline __attribute__((pure,always_inline)) int32_t getLen(Buffer * b) 
{
    return b->end - b->start;
}

そして、GCC(少なくとも私が試したいくつかのオンラインコンパイラバージョン)気づきました:

  1. 渡されたBuffer*パラメーターがグローバル値を指している場合、この関数の呼び出しは最適化されません(つまり、複数回呼び出されます)
  2. 渡されたポインターがローカル(スタック)変数を指している場合、この関数の呼び出しを最適化します(つまり、1回だけ呼び出します)。
  3. const代わりに関数をマークしても、どちらの場合も同じように機能しますが、ポインタ引数がある場合はpureおそらくconst無視されますか?

これは良いことです。グローバルBufferはいつでも別のスレッド/割り込みによって変更される可能性がありますが、ローカルBufferは最適化に対して完全に安全です。

しかし、私はポインタの受け渡しに関する発言に完全に混乱しています。pureポインタ引数を受け入れる関数に対してGCCの動作が明示的に定義されている場所はありますか?

ecatmur

ポインタ引数を受け入れる純粋関数に対してGCCの動作が明示的に定義されている場所はありますか?

動作は、ポインター引数をとらない純粋関数と同じです。プログラム内の任意のメモリを読み取ることはできますが、メモリに書き込んだりIOを実行したりすることはできません。

pure関数とconst関数をインラインとして記述することで、物事を大幅に混乱させました。関数本体が呼び出しサイトでコンパイラーに使用可能である場合、呼び出された関数が実行する操作をそれ自体で計算できます。pure属性とconst属性は、別のコンパイルユニットで定義されるため、関数本体が表示されない場合に最も役立ちます。

たとえば、次の非純粋、純粋、およびconst関数のコレクションについて考えてみます。

__attribute__((__pure__)) int a();
__attribute__((__const__)) int b();
void c();

私たちが呼び出した場合a何も操作が介在しないで、2回連続しているので、我々は、単一の呼び出しにそれを折りたたむことができaだけで、それを読むためにアクセスグローバルメモリに保証されています。別のスレッドがほぼ同時にグローバルメモリに書き込む場合でも、aそのスレッドと通信する方法がないため、コンパイラは、次の両方の呼び出しの前または後に書き込みが行われると想定できますa

int f() {
    int i = a();
    i += a();
    return i;  // optimized to "return a() * 2;"
}

の呼び出しのc間に呼び出す場合a、の戻り値は次aの呼び出しの影響を受ける可能性があると想定する必要がありますc

int g() {
    int i = a();
    c();
    i += a();
    return i;  // no optimization possible
}

ただし、純粋なaconstの代わりに、constを呼び出す場合は、次のように書き込む可能性のあるメモリを読み取ることができないbため、これを1回の呼び出しにまとめるbことができますc

int h() {
    int i = b();
    c();
    i += b();
    return i;  // optimized to "c(); return b() * 2;"
}

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

純粋関数、なぜ最適化がないのですか?

分類Dev

GCCとClang:純粋な最適化をオフにします

分類Dev

関数の開始/終了の最適化(gcc)

分類Dev

rxjsの純粋関数

分類Dev

C関数の最適化

分類Dev

KDB:関数の最適化

分類Dev

GCC-関数のインライン化、LTO、および最適化

分類Dev

ループまたは再帰を含む単純な関数の最適化

分類Dev

JavaScript純粋関数

分類Dev

GCCは再帰関数の最適化を末尾呼び出ししません

分類Dev

Spark数値関数の最適化(python)

分類Dev

Fortran純粋関数でのローカル変数の宣言と初期化

分類Dev

純粋な仮想関数の問題

分類Dev

DのC ++ DLL(純粋仮想関数)

分類Dev

C ++ 11の純粋仮想関数

分類Dev

JQuery-Is()関数の最適化

分類Dev

再帰関数の最適化

分類Dev

総和関数の最適化-GEKKO

分類Dev

MATLAB:最適化関数の設定

分類Dev

時間範囲関数の最適化

分類Dev

Javascriptクラス-関数の最適化(関数内の関数)

分類Dev

gccで純粋関数を宣言して定義する方法は?

分類Dev

関数が純粋でない場合は、GCCに対して純粋または定数として宣言することの効果

分類Dev

仮想純粋関数

分類Dev

Python での関数の複数の出力変数の最適化

分類Dev

仮想関数と純粋仮想関数の違い

分類Dev

アセンブリの関数型コード?(純粋関数)

分類Dev

この関数を純粋関数に変換する方法は?

分類Dev

Pythonの数学関数の最適化と高速化