2009-04-27 12 views
142

すべてのプラットフォームが歓迎です。答えにプラットフォームを指定してください。プログラムによってキャッシュラインサイズを取得しますか?

同様の質問:x86でHow to programmatically get the CPU cache page size in C++?

+5

FWIW、C++ 17はこれのコンパイル時の近似を提供します:http://stackoverflow.com/questions/39680206/understanding-stdhardware-destructive-interference-size-and-stdhardware-cons – GManNickG

答えて

29

、あなたはキャッシュとTLBの様々な特性を測定するために機能2とCPUID命令を使用することができます。関数2の出力を解析するのはやや複雑なので、Intel Processor Identification and the CPUID Instructionの3.1.3節(PDF)を参照してください。

このデータをC/C++コードから取得するには、インラインアセンブリ、コンパイラ組み込み関数を使用するか、外部アセンブリ関数を呼び出してCPUID命令を実行する必要があります。

+0

誰でも知っているキャッシュを内蔵した他のプロセッサでこれを行う方法は? – paxos1977

+2

@ceretullis:Errr ... x86にはキャッシュが組み込まれています。あなたが特に探しているのは他のどのプロセッサですか?あなたが求めているのはプラットフォームに依存しています。 –

2

また、タイミングを測定することでプログラム的に行うこともできます。明らかに、それは常にcpuidと同様に正確ではないが、より移植性が高い。 ATLASあなたはそれを見てみたいことがあり、その設定の段階でそれをしない:(合理的に最近のカーネルで)Linuxの

http://math-atlas.sourceforge.net/

143

、あなたが/ 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 

これは、あなたが今までにもCPUは、このキャッシュを共有するものとして、キャッシュラインサイズを含む、知っていると思っていたいあなたのキャッシュの詳細情報を提供します。これは、共有データを使用してマルチスレッドプログラミングを行っている場合に非常に便利です(データを共有するスレッドがキャッシュを共有している方が良い結果が得られます)。 Windowsプラットフォームで

+4

ファイルのどれにキャッシュラインサイズが含まれていますか?私はcoherency_line_sizeを仮定していますか?またはphysical_line_partition? – paxos1977

+19

coherency_line_size – spinfire

+5

これは確かに:これはバイト単位ですか? –

6

http://blogs.msdn.com/oldnewthing/archive/2009/12/08/9933836.aspx

からGetLogicalProcessorInformation 機能は システムによりあなた使用中の論理プロセッサの を特性が得られます。機能によって戻された SYSTEM_LOGICAL_PROCESSOR_INFORMATION を、RelationCacheタイプの エントリを探して歩くことができます。各 そのようなエントリは エントリはに適用され、 CACHE_DESCRIPTORで、それはキャッシュの 種類が記載され、キャッシュラインはそのためであるどのように大きな されているかを表示しますどのプロセッサ(複数可)を説明しますProcessorMask が含まれています キャッシュ。

104

Linuxでは、sysconf(3)を参照してください。

sysconf (_SC_LEVEL1_DCACHE_LINESIZE) 

また、それは、getconfを使用して、コマンドラインから取得することができます:私はいくつかのキャッシュラインのものに取り組んでおり、クロスプラットフォームの機能を書き込むために必要されている

$ getconf LEVEL1_DCACHE_LINESIZE 
64 
+3

簡単な答えは最高です! –

+0

ユニットとは何ですか?ビットまたはバイト? – warunapww

+1

@warunapwwバイト単位です。最終的に –

100

。私は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 
+11

linuxではsysconf(_SC_LEVEL1_DCACHE_LINESIZE)を使用する方が良いかもしれません。 – Matt

4

のARMv6以上はC0またはキャッシュタイプレジスタを持っています。ただし、特権モードでのみ使用できます。例えば

Cortex™-A8 Technical Reference Manualから:

キャッシュタイプレジスタの目的は、無効にすべき アドレスの範囲を可能にするために、バイト単位で指示 とデータキャッシュ最小線長さを決定することです。

キャッシュタイプレジスタがある:

  • 読み取り専用のみの特権モードでアクセス可能
  • を登録します。

キャッシュタイプレジスタの内容は、特定の の実装に依存します。図3-2は、キャッシュ タイプレジスタのビット配置を示しています...


ARMプロセッサは、(明らかに、いくつかの一つせずに構成することができます)キャッシュを持っていると仮定しないでください。これを判断する標準的な方法は、via C0です。 ARM ARMから、ページB6-6:

のARMv6から、システム制御コプロセッサキャッシュタイプレジスタは、キャッシュタイプが ページB6-14に登録参照、L1キャッシュを定義するための 義務付け方法です。これはアーキテクチャの以前のバリアントである のための推奨される方法です。さらに、ページB6-12の キャッシュの追加レベルについての考慮事項は、レベル2のキャッシュのサポートのためのアーキテクチャガイドラインを説明しています。

5

あなたがSDL2を使用している場合は、この機能を使用することができます。

バイトで、L1キャッシュラインサイズのサイズを返します
int SDL_GetCPUCacheLineSize(void); 

。このコードスニペットを実行している私のx86_64のマシンで

、:

printf("CacheLineSize = %d",SDL_GetCPUCacheLineSize()); 

は、私は少し遅れだが、知っているだけで、将来の訪問者のための情報を付加するCacheLineSize = 64

を生成します。 SDLのドキュメントでは現在、返される数値はKB単位ですが、実際にはバイト数です。

+0

これは本当に役に立ちます。私はSDL2でいくつかのゲームを書くつもりです。これは本当に便利になるでしょう –