1

参照によって2つの変数を取る単純な関数があります:

void foo(int*& it2,
         bit_reader<big_endian_tag>& reader2)
{
    for(/* ... */)
    {
        *it2++ = boo(reader2.next());
        // it2++ => 0x14001d890 add qword ptr [r12], 0x4
    }
}

ここでの問題は、 forit2reader2オプティマイザーが、ループ中にコンピューターにレジスターではなくメモリーへの書き込みをさせることです。

ただし、次のコードは、ループ中に変数を適切にレジスターに入れますが、ループの前後に不要なコピーの形で余分なオーバーヘッドがあります。

void foo2(int*& it2,
         bit_reader<big_endian_tag>& reader2)
{
    auto reader = reader2;
    auto it     = it2;

    for(/* ... */)
    {
        *it++ = boo(reader.next());
        // it++ => 0x14001d890 add r15, 0x4
    }

    reader2 = reader;
    it2 = it;
}

例えば

最初の例で 2 番目の例と同じコードを生成するようにするにはどうすればよいですか?ただし、余分なコピーはありません。

4

3 に答える 3

5

問題は、コンパイラがit2関数内で変更されていないことを証明できないことです。(まあ、それは可能ですが、それは通常のC ++コンパイラの意図された機能をはるかに超えています。)

boo(reader2.next());値が変わらないことをどうやって知るのですか?検討:

int* i = 0;

struct foo
{
    int myInt;
    int blah() { i = &myInt; return 5; }
};

void bar(int*& ptr, const foo& f)
{
    *ptr = f.blah(); // changes value of ptr!
}

int otherInt;
i = &otherInt;

bar(i, foo());

これはに何も割り当てませんがotherInt、変換後は次のようになります。

void bar(int*& ptr, const foo& f)
{
    int* ptrCopy = ptr;
    *ptrCopy = f.blah(); // changes ptr, but not ptrCopy
}

したがって、コンパイラが動作が同じであることを証明できない限り、最適化を行うことはできません。

C99はrestrictキーワードでこの問題を解決しますが、C++には同等のものがありません。__restrict__ただし、やなど、ほとんどのC++コンパイラに存在する拡張機能があります__restrict

標準のC++でそれを行うには、明示して自分でコピーを作成する必要があります

于 2012-08-15T21:41:31.863 に答える
1

まあ、できません。

非定数参照でパラメーターを渡す場合は、コンパイラーに元の変数を更新するように依頼します。したがって、新しい値をメモリに書き込む必要があります。

于 2012-08-15T21:41:27.127 に答える
0

「メモリ階層」の最適化がすべてです。レジスタで直接実行すると計算が最速になります。そのため、メモリから何かを計算するにレジスタにコピーしてから、結果をコピーして戻す必要があります。必要なメモリの場所。レジスタで直接計算することによって得られるパフォーマンスは、一般に、レジスタとの間でメモリをロードおよび保存するコストを相殺します。

メモリからレジスタに確実にデータを取得するにはどうすればよいですか? 例えば

size_t size;
double* arr;
for (int i = 0; i < size - 1; ++i) {
    double a = arr[i];     // copy to register
    double b = arr[i + 1]; // copy to register
    b = a*b + b;           // make sure flop computation is done in registers
    arr[i] = b;            // copy back to memory
}
于 2012-08-15T21:54:25.947 に答える