3

memcpy を使用して、可変サイズのデータ​​と固定サイズのデータ​​の両方をコピーします。場合によっては、少量のメモリ (ほんの数バイト) をコピーします。GCCでは、memcpyが組み込み/組み込みであったことを思い出します。ただし、(valgrind を使用して) コードをプロファイリングすると、glibc で実際の「memcpy」関数が何千回も呼び出されます。

組み込み関数を使用するには、どのような条件を満たす必要がありますか? 私は自分の memcpy をすばやくロールバックできますが、ビルトインは私ができることよりも効率的であると確信しています。

注: ほとんどの場合、コピーされるデータの量は、コンパイル時の定数として利用できます。

CXXFLAGS: -O3 -DNDEBUG

私が現在使用しているコードでは、ビルトインを強制しています。_ builtinプレフィックスを外すと、ビルトインは使用されません。これは、T=sizeof(type) を使用して他のさまざまなテンプレート/関数から呼び出されます。使用されるサイズは、1、2、4 の倍数、いくつかの 50 ~ 100 バイト サイズ、およびいくつかのより大きな構造です。

template<int T>
inline void load_binary_fixm(void *address)
{
    if( (at + T) > len )
        stream_error();

    __builtin_memcpy( address, data + at, T );
    at += T;
}
4

1 に答える 1

2

Tが小さい場合は、ネイティブ割り当てを専門にして使用します。

たとえば、Tが1の場合、1つの文字を割り当てるだけです。

アドレスが整列していることがわかっている場合は、プラットフォームに適したサイズのint型を使用してください。

アドレスが整列されていない場合は、適切な数の文字の割り当てを行う方がよい場合があります。

これのポイントは、分岐を避けてカウンターを維持することです。

Tが大きい場合、ライブラリmemcpy()よりも優れているとしたら、驚かれることでしょう。関数呼び出しのオーバーヘッドは、おそらくノイズの中で失われるでしょう。最適化したい場合は、周りのmemcpy()実装を見てください。拡張命令などを使用するバリアントがあります。

アップデート:

memcpyのインライン化に関する実際の(!)質問を見ると、コンパイラのバージョンやプラットフォームなどの質問が関連するようになります。好奇心から、次のようなstd::copyを使用してみましたか。

template<int T>
inline void load_binary_fixm(void *address)
{
    if( (at + T) > len )
        stream_error();

    std::copy(at, at + T, static_cast<char*>(address));
    at += T;
}
于 2010-11-15T00:06:10.180 に答える