誤った共有を防ぐために、配列の各要素をキャッシュラインに揃えたいと思います。そのため、まずキャッシュラインのサイズを知る必要があるため、各要素にそのバイト数を割り当てます。第二に、配列の開始点をキャッシュラインに揃えたい。
Linuxと8コアのx86プラットフォームを使用しています。まず、キャッシュラインサイズを見つける方法を教えてください。第二に、Cのキャッシュラインに合わせるにはどうすればよいですか。gccコンパイラを使用しています。
したがって、キャッシュラインサイズが64であると仮定すると、構造はたとえば次のようになります.
element[0] occupies bytes 0-63
element[1] occupies bytes 64-127
element[2] occupies bytes 128-191
など、0-63がキャッシュラインに揃えられていることを前提としています。
サイズを知るには、プロセッサのドキュメントを使用して検索する必要がありますが、プログラムによる方法はありません。ただし、プラス面では、ほとんどのキャッシュラインは、Intel標準に基づいた標準サイズです。 x86のキャッシュラインは64バイトですが、誤った共有を防ぐために、ターゲットとするプロセッサのガイドラインに従う必要があります(インテルはネットバーストベースのプロセッサに関する特別な注意事項を持っています)。通常、このために64バイトに合わせる必要があります(Intelは、16バイトの境界をまたがらないようにする必要があると述べています)。
CまたはC++でこれを行うには、標準の_aligned_alloc
_関数、または__attribute__((align(64)))
や__declspec(align(64))
などのコンパイラ固有の指定子のいずれかを使用する必要があります。構造体のメンバー間をパディングして異なるキャッシュラインに分割するには、次の64バイトの境界に揃えるのに十分な大きさのメンバーを挿入する必要があります
Linuxと8コアのx86プラットフォームを使用しています。まず、キャッシュラインサイズを見つける方法を教えてください。
_$ getconf LEVEL1_DCACHE_LINESIZE
64
_
値をマクロ定義としてコンパイラに渡します。
_$ gcc -DLEVEL1_DCACHE_LINESIZE=`getconf LEVEL1_DCACHE_LINESIZE` ...
_
実行時にsysconf(_SC_LEVEL1_DCACHE_LINESIZE)
を使用してL1キャッシュサイズを取得できます。
キャッシュラインサイズを取得するための完全に移植可能な方法はありません。ただし、x86/64を使用している場合は、cpuid
命令を呼び出して、サイズ、キャッシュラインサイズ、レベル数など、キャッシュに関する必要な情報をすべて取得できます。
http://softpixel.com/~cwright/programming/simd/cpuid.php
(少し下にスクロールすると、ページはSIMDについてのものですが、キャッシュラインを取得するセクションがあります。)
データ構造の調整に関しては、完全に移植可能な方法もありません。 GCCとVS10には、構造体の配置を指定するさまざまな方法があります。それを「ハッキング」する1つの方法は、必要なアライメントに一致するまで、未使用の変数で構造体をパディングすることです。
Mallocs()を調整するために、すべてのメインストリームコンパイラには、そのためのmalloc関数も調整されています。
もう1つの簡単な方法は、/ proc/cpuinfoをcatするだけです。
cat/proc/cpuinfo | grep cache_alignment
posix_memalignまたはvalloc を使用して割り当てられたメモリをキャッシュラインに揃えます。
誰かがC++でこれを簡単に行う方法に興味があるなら、キャッシュラインサイズと参照されるT
オブジェクトの配置を決定するCacheAligned<T>
_クラスを持つライブラリを構築しました_CacheAligned<T>
_オブジェクトで.Ref()
を呼び出します。キャッシュラインのサイズが事前にわかっている場合、または非常に一般的な値である64(バイト)をそのまま使用する場合は、_Aligned<typename T, size_t Alignment>
_を使用することもできます。