10

最近、自分のアプリケーションで false-sharing と思われる問題に遭遇したので、データをキャッシュラインに合わせる方法に関するSutter の記事を調べました。彼は次の C++ コードを提案しています。

// C++ (using C++0x alignment syntax)
template<typename T>
struct cache_line_storage {
   [[ align(CACHE_LINE_SIZE) ]] T data;
   char pad[ CACHE_LINE_SIZE > sizeof(T)
        ? CACHE_LINE_SIZE - sizeof(T)
        : 1 ];
};

CACHE_LINE_SIZE > sizeof(T)が true の場合、これがどのように機能するかがわかります。構造体cache_line_storageは、メモリの 1 つの完全なキャッシュ ラインを占有するだけです。ただし、が 1 つのキャッシュ ラインよりも大きい場合は、結果の構造体のサイズがキャッシュ ライン サイズの整数倍になるようにsizeof(T)、データをバイト単位でパディングする必要があると思います。CACHE_LINE_SIZE - T % CACHE_LINE_SIZE私の理解の何が問題になっていますか?なぜ 1 バイトのパディングで十分なのですか?

4

3 に答える 3

7

サイズ 0 の配列を持つことはできないため、コンパイルするには 1 が必要です。ただし、仕様の現在のドラフト バージョンでは、そのようなパディングは不要であると述べられています。コンパイラは、構造体のアラインメントまでパディングする必要があります。

CACHE_LINE_SIZEが より小さい場合、このコードの形式が正しくないことにも注意してくださいalignof(T)。これを修正するには、おそらく を使用する必要があります[[align(CACHE_LINE_SIZE), align(T)]]。これにより、より小さな位置合わせが決して選択されないようになります。

于 2009-11-16T20:53:59.770 に答える
3

想像

#define CACHE_LINE_SIZE 32
sizeof(T) == 48

では、 がどのよう[[ align(CACHE_LINE_SIZE) ]]に機能するかを考えてみましょう。例えば:

[[ align(32) ]] Foo foo;

これはsizeof(Foo) == 32nいくつかのn. つまり、必要に応じて align() がパディングを行い、要求どおりFoo foo[10];にそれぞれをfoo[i]整列させることができます。

したがって、私たちの場合、 を使用するとsizeof(T) == 48、これは を意味しsizeof(cache_line_storage<T>) == 64ます。

したがって、アライメントにより、期待していたパディングが得られます。

ただし、これはテンプレートの 1 つの「エラー」です。このケースを考えてみましょう:

#define CACHE_LINE_SIZE 32
sizeof(T) == 32

ここで、 になりchar pad[1];ます。つまりsizeof(cache_line_storage<T>) == 64。おそらくあなたが望むものではありません!

テンプレートを多少変更する必要があると思います:

template <typename T, int padding>
struct pad_or_not
{
   T data;
   char pad[padding];
};

// specialize the 0 case
// As it is late, I am SURE I've got the specialization syntax wrong...
template <typename T, int>
struct pad_or_not<0>
{
   T data;
};

template<typename T>
struct cache_line_storage {
   [[ align(CACHE_LINE_SIZE) ]] pad_or_not<T, (sizeof(T) > CACHE_LINE_SIZE ? 0 : CACHE_LINE_SIZE - sizeof(T) ) > data;
};

またはそのようなもの。

于 2009-11-17T05:39:23.123 に答える
0

「サイズ 0 の配列を持つことはできないため、コンパイルするには 1 が必要です」 - GNU C では、次元が 0 の配列を使用できます。http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Zero-Length.htmlも参照してください。

于 2010-08-25T05:53:06.283 に答える