web-dev-qa-db-ja.com

Intel x86プロセッサのL1メモリキャッシュはどこに文書化されていますか?

アルゴリズムのプロファイルを作成して最適化しようとしています。さまざまなプロセッサに対するキャッシュの特定の影響を理解したいと思います。最近のIntel x86プロセッサー(Q9300など)では、キャッシュ構造に関する詳細情報を見つけるのは非常に困難です。特に、ポストプロセッサの仕様を含むほとんどのWebサイト( (Intel.com を含む)には、L1キャッシュへの参照が含まれていません。これは、L1キャッシュが存在しないためか、この情報が何らかの理由で重要ではないと考えられているためですか? L1キャッシュの削除に関する記事や議論はありますか?

[編集]さまざまなテストと診断プログラム(主に以下の回答で説明されているもの)を実行した後、私のQ9300に32K L1データキャッシュがあるように思われました。この情報を入手するのがなぜ難しいのかについて、私はまだ明確な説明を見つけていません。現在の私の理論では、L1キャッシングの詳細はIntelによって企業秘密として扱われています。

50
nobar

Intelキャッシュの仕様を見つけることはほぼ不可能です。昨年キャッシュについてクラスを教えていたときに、インテル内部(コンパイラグループ)の友達に尋ねたところ、彼らは仕様を見つけることができませんでした。

でも待ってください!!!Jed 、彼の魂を祝福して、Linuxシステムでは多くの情報を絞り出すことができると私たちに伝えますカーネルの:

grep . /sys/devices/system/cpu/cpu0/cache/index*/*

これにより、関連性、セットサイズ、およびその他の情報(レイテンシではない)が得られます。たとえば、AMDは128K L1キャッシュをアドバタイズしますが、AMDマシンにはそれぞれ64Kの分割IおよびDキャッシュがあることがわかりました。


Jedのおかげで現在はほとんど使用されていない2つの提案:

  • AMDはキャッシュに関する多くの情報を公開しているため、少なくとも最新のキャッシュに関する情報を入手できます。たとえば、昨年のAMD L1キャッシュは、サイクル(ピーク)あたり2ワードを配信しました。

  • オープンソースツール valgrind には、あらゆる種類のキャッシュモデルが含まれており、キャッシュ動作のプロファイリングと理解に非常に役立ちます。 KDE SDKの一部である、非常に優れた視覚化ツールkcachegrindが付属しています。


例:2008年第3四半期、AMD K8 / K1 CPUは64バイトのキャッシュラインを使用し、L1I/L1Dスプリットキャッシュはそれぞれ64kBです。 L1Dは2ウェイアソシアティブで、L2とは排他的で、レイテンシは3サイクルです。 L2キャッシュは16ウェイアソシアティブで、レイテンシは約12サイクルです。

AMD BulldozerファミリCP 16kiBの4ウェイ連想L1D(クラスターあたり2)(コアあたり2)のスプリットL1を使用します。

Intel CPUは、L1を長い間同じに保ちました(Pentium Mから Haswell にSkylakeへ、そしてその後、おそらく多くの世代):各IおよびDキャッシュを32kBに分割し、L1Dを8ウェイアソシアティブにします。 。 DDR DRAMのバースト転送サイズと一致する64バイトのキャッシュライン。ロード使用のレイテンシは最大4サイクルです。

さらにパフォーマンスとマイクロアーキテクチャデータへのリンクについては、 x86 タグwikiも参照してください。

61
Norman Ramsey

このIntelマニュアル:Intel®64およびIA-32アーキテクチャー最適化リファレンスマニュアルには、キャッシュの考慮事項についての適切な説明があります。

enter image description here

ページ46、セクション2.2.5.1 インテル®64およびIA-32アーキテクチャー最適化リファレンスマニュアル

MicroSlopでさえ、キャッシュの使用状況とパフォーマンスを監視するためのより多くのツールの必要性に目覚めており、 GetLogicalProcessorInformation()関数 の例があります(...プロセス内の関数名)私はコードアップすると思います。

UPDATE I:Hazwellは Inside the Tockからキャッシュロードパフォーマンスを2倍に向上させます。ハスウェルの建築

キャッシュを最大限に活用することがどれほど重要であるか疑問がある場合は、 以前のAzulのCliff Clickによるこのプレゼンテーション は、疑いを払拭する必要があります。彼の言葉では、「メモリは新しいディスクです!」です。

Haswell’s URS (Unified Reservation Station)

更新II:SkyLakeの大幅に改善されたキャッシュパフォーマンスの仕様

SkyLake Cache Specifications

26
user1899861

さらに調査を行いました。 ETHチューリッヒには メモリパフォーマンス評価ツール を構築したグループがあり、少なくともL1およびL2キャッシュのサイズ(および関連性)に関する情報を取得できる可能性があります。このプログラムは、さまざまな読み取りパターンを実験的に試し、結果のスループットを測定することで機能します。 BryantとO'Hallaronによる人気の教科書 には簡略版が使用されました。

8
Norman Ramsey

あなたは開発者の仕様ではなく、消費者の仕様を見ています。 必要なドキュメントはこちらです キャッシュサイズはプロセッサフ​​ァミリのサブモデルによって異なるため、通常、IA-32開発マニュアルには記載されていませんが、NewEggなどで簡単に調べることができます。

編集:より具体的に:第3巻(システムプログラミングガイド)の第10章、最適化リファレンスマニュアルの第7章、およびTLBページの内容キャッシングマニュアル。ただし、L1から離れていると思います。

8
Not Sure

これらのプラットフォームにはL1キャッシュが存在します。これは、メモリとフロントサイドのバス速度がCPUの速度を超えるまでほぼ間違いなく当てはまります。これはかなり長い道のりです。

Windowsでは、 GetLogicalProcessorInformation を使用して、一定レベルのキャッシュ情報(サイズ、行サイズ、結合性など)を取得できます。Win7のExバージョンは、どのコアがどのキャッシュを共有するかなど、さらに多くのデータを提供します。 CpuZ もこの情報を提供します。

2
Michael

参照の局所性 は、一部のアルゴリズムのパフォーマンスに大きな影響を与えます。 L1、L2(および新しいCPU L3では)キャッシュのサイズと速度は、明らかにこれに大きな役割を果たします。行列の乗算は、そのようなアルゴリズムの1つです。

2
Mitch Wheat

IntelマニュアルVol。 2は、キャッシュサイズを計算する次の式を指定します。

このキャッシュサイズ(バイト)

=(方法+ 1)*(パーティション+ 1)*(Line_Size + 1)*(セット+ 1)

=(EBX [31:22] + 1)*(EBX [21:12] + 1)*(EBX [11:0] + 1)*(ECX + 1)

WaysPartitionsLine_Size、およびSetsは、cpuidを使用してクエリされ、eax0x04に設定されます。

ヘッダーファイル宣言の提供

x86_cache_size.h

unsigned int get_cache_line_size(unsigned int cache_level);

実装は次のようになります。

;1st argument - the cache level
get_cache_line_size:
    Push rbx
    ;set line number argument to be used with CPUID instruction
    mov ecx, edi 
    ;set cpuid initial value
    mov eax, 0x04
    cpuid

    ;cache line size
    mov eax, ebx
    and eax, 0x7ff
    inc eax

    ;partitions
    shr ebx, 12
    mov edx, ebx
    and edx, 0x1ff
    inc edx
    mul edx

    ;ways of associativity
    shr ebx, 10
    mov edx, ebx
    and edx, 0x1ff
    inc edx
    mul edx

    ;number of sets
    inc ecx
    mul ecx

    pop rbx

    ret

私のマシンではどちらが次のように機能します:

#include "x86_cache_size.h"

int main(void){
    unsigned int L1_cache_size = get_cache_line_size(1);
    unsigned int L2_cache_size = get_cache_line_size(2);
    unsigned int L3_cache_size = get_cache_line_size(3);
    //L1 size = 32768, L2 size = 262144, L3 size = 8388608
    printf("L1 size = %u, L2 size = %u, L3 size = %u\n", L1_cache_size, L2_cache_size, L3_cache_size);
}
1
St.Antario