すべてのプラットフォームを歓迎します。回答のプラットフォームを指定してください。
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プラットフォームの場合:
from http://blogs.msdn.com/oldnewthing/archive/2009/12/08/9933836.aspx
GetLogicalProcessorInformation関数は、システムで使用されている論理プロセッサの特性を提供します。 RelationCacheタイプのエントリを検索する関数によって返されるSYSTEM_LOGICAL_PROCESSOR_INFORMATIONを調べることができます。そのような各エントリには、エントリが適用されるプロセッサを示すProcessorMaskが含まれ、CACHE_DESCRIPTORでは、記述されているキャッシュのタイプとそのキャッシュのキャッシュラインの大きさを示します。
ARMv6以降には、C0
(またはキャッシュタイプレジスタがあります。ただし、特権モードでのみ使用可能です。
たとえば、 Cortex™-A8テクニカルリファレンスマニュアル から:
キャッシュタイプレジスタの目的は、命令およびデータキャッシュのバイト単位の最小ライン長を決定して、アドレス範囲を無効化することです。
キャッシュタイプレジスタは次のとおりです。
- 読み取り専用レジスタ
- 特権モードでのみアクセス可能。
キャッシュタイプレジスタの内容は、特定の実装によって異なります。図3-2は、キャッシュタイプレジスタのビット配置を示しています...
ARMプロセッサーにキャッシュがあるとは思わないでください(明らかに、キャッシュなしで構成できるものもあります)。それを決定する標準的な方法は、C0
によるものです。 ARM ARM から、B6-6ページ:
ARMv6から、システム制御コプロセッサーキャッシュタイプレジスタは、L1キャッシュを定義するための必須メソッドです。ページB6-14のキャッシュタイプレジスタを参照してください。これは、アーキテクチャの以前のバリアントの推奨方法でもあります。また、B6-12ページのキャッシュの追加レベルの考慮事項では、レベル2キャッシュサポートのアーキテクチャガイドラインについて説明します。
また、タイミングを測定することにより、プログラムで実行することもできます。明らかに、それは常にcpuidなどと同じくらい正確ではありませんが、より移植性があります。 ATLASはその構成段階でそれを行います。あなたはそれを見たいかもしれません: