C++ で CPU のキャッシュ サイズを決定する方法はありますか? 大量のデータを処理するアルゴリズムがあり、キャッシュに収まるようにこのデータをチャンクに分割したいと考えています。これは可能ですか?キャッシュサイズを念頭に置いたプログラミングに関するその他のヒントを教えてください (特にマルチスレッド/マルチコア データ処理に関して)。
ありがとう!
C++ で CPU のキャッシュ サイズを決定する方法はありますか? 大量のデータを処理するアルゴリズムがあり、キャッシュに収まるようにこのデータをチャンクに分割したいと考えています。これは可能ですか?キャッシュサイズを念頭に置いたプログラミングに関するその他のヒントを教えてください (特にマルチスレッド/マルチコア データ処理に関して)。
ありがとう!
「すべてのプログラマがメモリについて知っておくべきこと」によると、Ulrich Drepper による Linux で次のことができます。
メモリ要件の公式が得られたら、それをキャッシュ サイズと比較できます。前述のように、キャッシュは他の複数のコアと共有される場合があります。現在、{間違いなくすぐにもっと良い方法があるでしょう!} 知識をハードコーディングせずに正しい情報を取得する唯一の方法は、/sys ファイルシステムを使用することです。表 5.2 では、カーネルがハードウェアについて公開しているものを見てきました。プログラムは次のディレクトリを見つける必要があります。
/sys/devices/system/cpu/cpu*/cache
これはSection 6: What Programmers Can Doにリストされています。
彼はまた、図 6.5 のすぐ下に、OS から取得できない場合に L1D キャッシュ サイズを決定するために使用できる短いテストについても説明しています。
彼の論文でもう 1 つ出くわした sysconf(_SC_LEVEL2_CACHE_SIZE)
ことがあります。十分に文書化されていないように見えますが、L2 キャッシュ サイズを返すことになっている Linux のシステム コールです。
C++ 自体は CPU キャッシュを「気に」しないため、言語に組み込まれているキャッシュ サイズのクエリはサポートされていません。Windows 向けに開発している場合は、CPU キャッシュに関する情報を照会するために使用できるGetLogicalProcessorInformation() 関数があります。
大きな配列を事前に割り当てます。次に、各要素に順番にアクセスし、各アクセスの時間を記録します。理想的には、キャッシュ ミスが発生したときにアクセス時間が急増します。次に、L1 キャッシュを計算できます。うまくいかないかもしれませんが、試してみる価値があります。
興味深いことに、私は少し前にこれを行うプログラムを作成しました (ただし C ですが、C++ コードに簡単に組み込むことができると確信しています)。
http://github.com/wowus/CacheLineDetection/blob/master/Cache%20Line%20Detection/cache.c
get_cache_line 関数は興味深いもので、配列アクセスのタイミング データで最大のスパイクの直前の位置を返します。私のマシンで正しく推測しました!それ以外の場合は、自分で作成するのに役立ちます。
これは、もともと私の興味をそそったこの記事に基づいています: http://igoro.com/archive/gallery-of-processor-cache-effects/
cpu (x86) の cpuid を読み取り、ルックアップ テーブルによってキャッシュ サイズを決定します。テーブルには、CPU の製造元がプログラミング マニュアルで公開しているキャッシュ サイズを入力する必要があります。
IIRC、GCC に__builtin_prefetch
ヒントがあります。
http://gcc.gnu.org/onlinedocs/gcc-3.3.6/gcc/Other-Builtins.html
これに関する優れたセクションがあります。基本的に、それは示唆しています:
__builtin_prefetch (&array[i + LookAhead], rw, locality);
ここで、rwは 0 (読み取りの準備) または 1 (書き込みの準備) の値で、localityは 0 から 3 の数値を使用します。0 は局所性がなく、3 は非常に強い局所性です。
どちらもオプションです。LookAhead は、先読みする要素の数になります。メモリ アクセスが 100 サイクルで、展開されたループが 2 サイクル離れている場合、LookAhead は 50 または 51 に設定できます。
通常、キャッシュは正しいことを行います。通常のプログラマにとって唯一の本当の心配は偽共有であり、コンパイラ ディレクティブが必要なため、実行時にそれを処理することはできません。