すべてのプラットフォームを歓迎します。回答のプラットフォームを指定してください。
9 に答える
Linux(かなり最近のカーネルを使用)では、/sysから次の情報を取得できます。
/sys/devices/system/cpu/cpu0/cache/
このディレクトリには、キャッシュの各レベルのサブディレクトリがあります。これらの各ディレクトリには、次のファイルが含まれています。
coherency_line_size
level
number_of_sets
physical_line_partition
shared_cpu_list
shared_cpu_map
size
type
ways_of_associativity
coherency_line_size
これにより、キャッシュラインサイズ( )や、このキャッシュを共有するCPUなど、キャッシュに関する詳細情報が得られます。これは、共有データを使用してマルチスレッドプログラミングを行う場合に非常に役立ちます(データを共有するスレッドがキャッシュも共有している場合は、より良い結果が得られます)。
Linux では sysconf(3) を見てください。
sysconf (_SC_LEVEL1_DCACHE_LINESIZE)
getconf を使用してコマンド ラインから取得することもできます。
$ getconf LEVEL1_DCACHE_LINESIZE
64
私はいくつかのキャッシュ ラインに取り組んでおり、クロスプラットフォーム関数を作成する必要がありました。https://github.com/NickStrupat/CacheLineSizeの github リポジトリにコミットしました。または、以下のソースを使用することもできます。自由に好きなことをしてください。
#ifndef GET_CACHE_LINE_SIZE_H_INCLUDED
#define GET_CACHE_LINE_SIZE_H_INCLUDED
// Author: Nick Strupat
// Date: October 29, 2010
// Returns the cache line size (in bytes) of the processor, or 0 on failure
#include <stddef.h>
size_t cache_line_size();
#if defined(__APPLE__)
#include <sys/sysctl.h>
size_t cache_line_size() {
size_t line_size = 0;
size_t sizeof_line_size = sizeof(line_size);
sysctlbyname("hw.cachelinesize", &line_size, &sizeof_line_size, 0, 0);
return line_size;
}
#elif defined(_WIN32)
#include <stdlib.h>
#include <windows.h>
size_t cache_line_size() {
size_t line_size = 0;
DWORD buffer_size = 0;
DWORD i = 0;
SYSTEM_LOGICAL_PROCESSOR_INFORMATION * buffer = 0;
GetLogicalProcessorInformation(0, &buffer_size);
buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION *)malloc(buffer_size);
GetLogicalProcessorInformation(&buffer[0], &buffer_size);
for (i = 0; i != buffer_size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ++i) {
if (buffer[i].Relationship == RelationCache && buffer[i].Cache.Level == 1) {
line_size = buffer[i].Cache.LineSize;
break;
}
}
free(buffer);
return line_size;
}
#elif defined(linux)
#include <stdio.h>
size_t cache_line_size() {
FILE * p = 0;
p = fopen("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size", "r");
unsigned int i = 0;
if (p) {
fscanf(p, "%d", &i);
fclose(p);
}
return i;
}
#else
#error Unrecognized platform
#endif
#endif
x86 では、関数 2 でCPUID命令を使用して、キャッシュと TLB のさまざまなプロパティを確認できます。関数 2 の出力の解析はやや複雑なので、Intel Processor Identification and the CPUID Instruction (PDF) のセクション 3.1.3 を参照してください。
C/C++ コードからこのデータを取得するには、インライン アセンブリ、コンパイラ組み込み関数を使用するか、外部アセンブリ関数を呼び出して CPUID 命令を実行する必要があります。
SDL2 を使用している場合は、次の関数を使用できます。
int SDL_GetCPUCacheLineSize(void);
これは、L1 キャッシュ ライン サイズのサイズをバイト単位で返します。
私の x86_64 マシンで、次のコード スニペットを実行します。
printf("CacheLineSize = %d",SDL_GetCPUCacheLineSize());
プロデュースCacheLineSize = 64
少し遅れていることは承知していますが、将来の訪問者のために情報を追加するだけです. 現在、SDL のドキュメントには、返される数値は KB 単位であると記載されていますが、実際にはバイト単位です。
Windows プラットフォームの場合:
http://blogs.msdn.com/oldnewthing/archive/2009/12/08/9933836.aspxから
GetLogicalProcessorInformation 関数は、システムで使用されている論理プロセッサの特性を示します。タイプ RelationCache のエントリを探す関数によって返された SYSTEM_LOGICAL_PROCESSOR_INFORMATION をたどることができます。このような各エントリには、エントリが適用されるプロセッサを示す ProcessorMask が含まれており、CACHE_DESCRIPTOR では、記述されているキャッシュの種類とそのキャッシュのキャッシュ ラインの大きさを示します。
ARMv6C0
以降にはキャッシュ タイプ レジスタがあります。ただし、特権モードでのみ使用できます。
たとえば、Cortex™-A8 テクニカル リファレンス マニュアルから:
キャッシュ タイプ レジスタの目的は、命令およびデータ キャッシュの最小ライン長をバイト単位で決定して、アドレス範囲を無効化できるようにすることです。
キャッシュ タイプ レジスタは次のとおりです。
- 読み取り専用レジスタ
- 特権モードでのみアクセスできます。
キャッシュ タイプ レジスタの内容は、特定の実装によって異なります。図 3-2 は、キャッシュ タイプ レジスタのビット配置を示しています...
ARM プロセッサにキャッシュがあると仮定しないでください (キャッシュなしで構成できるものもあるようです)。それを決定する標準的な方法は、経由C0
です。ARM ARMの B6-6 ページから:
ARMv6 以降、システム コントロール コプロセッサ キャッシュ タイプ レジスタは、L1 キャッシュを定義するための必須の方法です。キャッシュ タイプ レジスタ(B6-14 ページ)を参照してください。これは、アーキテクチャの以前のバリアントにも推奨される方法です。さらに、B6-12 ページの追加キャッシュ レベルに関する考慮事項では、レベル 2 キャッシュ サポートのアーキテクチャ ガイドラインについて説明しています。
タイミングを測定することで、プログラムで実行することもできます。明らかに、常に cpuid などと同じくらい正確であるとは限りませんが、より移植性があります。ATLAS は構成段階でそれを行います。