目次
1.なぜメモリグレーディング戦略があるのですか?
メモリ分類戦略を理解したい。
まず、「ストレージをどのように見せたいか」、つまり「私たちのニーズは何か」を理解する必要があります。
次に、要件にどのような「実装の制約」があるかを理解する必要があります。
需要面では、メモリが高速で、サイズが小さく、スペースが大きく、エネルギー消費量が少なく、熱放散が良く、電源を切ってもデータが失われないことを望んでいます。しかし実際には、すべての要件を達成できないことがよくあります。
以下に、次のような詳細な経験をするためのいくつかの例を示します。
- メモリが小さい場合、そのストレージスペースは制限されます。
- メモリ電子部品の密度が高い場合、熱放散が問題になります。電子部品はすべて熱を発生するため、電子部品が非常に集中しているCPUでは、電子部品を冷却するために別のファンまたは水冷が必要です。
- メモリがCPUから遠く離れていると、必然的に伝送プロセスの遅延が発生するため、伝送速度も低下します。
ほとんどの人の知覚では、光の速度は非常に速く、信号は光の速度で伝わるため、ここで質問があるかもしれません。光の速度が非常に速いので、信号の遅延は小さくする必要があります。ただし、そうではありません。たとえば、クロック信号は1GHzのCPUであり、1Gは10億を表すため、クロック信号のサイクルは1/10億秒になります。光の速度は3×10から8平方メートル/秒、つまり3億メートル/秒です。したがって、1サイクルで、光は30センチメートルしか移動できません。
見て!マクロの世界では光の速度は非常に速いですが、コンピューターの世界では、光の速度は私たちが知覚するほど速くはありません。そのため、コンポーネントがCPUから少し離れていても、動作速度は大幅に低下します。
また、CPUに内部メモリを保存してみませんか?
これを行うと、回路全体の熱放散とサイズに加えて、サーバーに問題が発生し、サーバーがメモリをカスタマイズする方法がなくなります。つまり、CPUは工場出荷時にメモリサイズを決定します。より大きなメモリに変更する場合は、CPUを変更する必要があり、アセンブリのカスタマイズは非常に重要な要件であり、これは絶対に受け入れられません。
さらに、同じ価格で、メモリが高速であるほど、通常、そのエネルギー消費量は高くなります。エネルギー消費量が多いほど、発熱量は大きくなります。
したがって、ストレージテクノロジーに破壊的なブレークスルーがいつか発生しない限り、上記の要件を完全に満たすことはできません。
2.メモリグレーディング戦略
すべての要件を解決するためにメモリを使用することはできないため、要件を分類する必要があります。
実行可能な解決策は、データの使用頻度に応じて異なるメモリを使用することです。高周波で使用されるデータの読み取りと書き込みが速いほど良いので、最も高価な材料を使用して、最も近い場所に配置します。 CPU;データの使用頻度が低いほど、CPUから離れるほど、使用する材料は安価になります。
2.1メモリのレベル
- 登録;
- L1-キャッシュ;
- L2-キャッシュ;
- L3-Cahce;
- 羊;
- ハードディスク/ SSD。
- 登録
レジスタはCPUの制御ユニットと論理計算ユニットの隣にあり、使用する材料が最速です。先に述べたように、メモリ速度が速いほど、エネルギー消費量が多くなり、発熱量が多くなり、コストが最も高くなるため、数値を大きくすることはできません。
レジスタの数は通常、数十から数百の間であり、各レジスタを使用して特定のバイト(バイト)のデータを格納できます。といった:
- 32ビットCPUのほとんどのレジスタは、4バイトを格納できます。
- 64ビットCPUのほとんどのレジスタは、8バイトを格納できます。
レジスタのアクセス速度は非常に高速です。通常、CPUクロックサイクルの半分以内に読み取りと書き込みを完了する必要があります。たとえば、レジスタの読み取りと書き込みに加えて、4サイクルで完了する必要のある命令は、命令のデコード、命令の実行と計算の制御も必要です。レジスタ速度が遅すぎると、4サイクルで命令が完了しない場合があります。
2.2.1L1-キャッシュ
L1-はCPUにキャッシュされます。レジスタと比較すると、その場所はCPUコアから離れていますが、コストは低くなります。一般に、L1-Cacheのサイズは数十Kbから数百Kbの範囲であり、読み取りと書き込みの速度は2から4CPUクロックサイクルです。
2.2.2L2-キャッシュ
L2キャッシュもCPU内にあり、場所はL1キャッシュよりもCPUコアから離れています。そのサイズはL1-Cacheよりも大きく、具体的なサイズはCPUモデルによって異なります。2M、それよりも小さいまたは大きいものがあり、速度は10〜20CPUサイクルです。
2.2.3L3-キャッシュ
L3キャッシュもCPU内にあり、場所はL2キャッシュよりもCPUコアから離れています。サイズは通常L2-Cacheよりも大きく、読み取りと書き込みの速度は20〜60CPUサイクルです。L3キャッシュサイズもモデルによって異なります。たとえば、i9CPUには512KBのL1キャッシュ、2MBのL2キャッシュ、16MBのL3キャッシュがあります。
3.メモリ
メモリの主な材料は半導体シリコンで、マザーボードに挿入されて動作します。その場所はCPUからある程度離れているため、バスでCPUに接続する必要があります。メモリには独立したスペースがあるため、上記のメモリよりも大きく、コストもはるかに低くなります。最近の一部のパーソナルコンピュータのメモリは16Gですが、一部のサーバーのメモリは最大数テラバイトになる可能性があります。メモリ速度は約200〜300CPUサイクルです。
4.SSDとハードディスク
SSDはソリッドステートドライブとも呼ばれ、その構造はメモリに似ていますが、その利点は、停電後もデータが残っていることです。メモリ、レジスタ、およびキャッシュの電源をオフにすると、データは消えます。メモリの読み取りと書き込みの速度は、SSDの約10〜1000倍です。以前は、一種の物理的な読み取りおよび書き込みディスクがありました。これはハードディスクとも呼ばれ、その速度はメモリよりも約100W遅くなりました。速度が遅すぎるため、徐々にSSDに置き換えられています。
CPUがメモリにデータを必要とする場合、このデータがレジスタにある場合は直接使用できます。そのようなデータがレジスタにない場合は、最初にL1キャッシュにクエリを実行する必要があります。L1にない場合は、次に、L2キャッシュを照会します。L2にはありません。L3キャッシュを再度確認します。L3がないので、メモリに移動して取得します。
5.キャッシュエントリ構造
上記では、ストレージとそのメモリ階層構造の特性を紹介しましたが、キャッシュアルゴリズムとデータ構造の設計にはいくつかの問題があります。たとえば、CPUがメモリアドレスにアクセスしたい場合、データがL1キャッシュにあるかどうかを確認するにはどうすればよいですか?言い換えれば、キャッシュ内のデータ構造とアルゴリズムは何ですか?
キャッシュであろうとメモリであろうと、それらはすべて線形メモリです。つまり、データは隣り合って格納されます。メモリを1列しかないテーブルと考えると、キャッシュは複数の列を持つテーブルであり、このテーブルの各行はキャッシュエントリと呼ばれます。
スキーム1
キャッシュは基本的にキー値ストレージであり、そのキーはメモリアドレスであり、値はキャッシュ時のメモリアドレスの値です。最初に、単純なスキームであるキャッシュエントリの設計2列について考えてみましょう。
- メモリアドレス
- キャッシュされた値。
CPUがメモリアドレスを読み取るときに、エントリを追加します。メモリアドレスのデータがL1キャッシュにないかどうかを照会する場合は、各エントリをトラバースして、エントリ内のメモリアドレスが照会されたメモリアドレスと同じであるかどうかを確認できます。それらが同じである場合、エントリのキャッシュされた値を取り出します。
この方法では、キャッシュ内のすべてのエントリをトラバースする必要があるため、計算速度が非常に遅くなります。最悪の場合、アルゴリズムはすべてのエントリをチェックする必要があるため、これは実行可能な解決策ではありません。
スキーム2
実際、多くの優れたスキームは、最も愚かなスキームから変換されることがよくあります。これでスキームができましたが、このスキームでは、メモリアドレスがどの行にキャッシュされているかをすばやく判断できません。したがって、より良い方法を見つけたいと思います。メモリアドレスを見てみましょう。それがどの行にあるかをすばやく知ることができます。
ここでは、数学的方法を使用できます。たとえば、1000個のメモリアドレスがありますが、キャッシュエントリは10個だけです。メモリアドレスの数は0、1、2、3、...、999であり、キャッシュエントリの数は0〜9です。701などのメモリ番号について考え、それを10で割り切れる701などのキャッシュエントリに数学的にマッピングして、キャッシュエントリ1を取得します。
このようにして、メモリアドレスを取得するたびに、そのキャッシュエントリをすばやく特定できます。次に、キャッシュエントリのメモリアドレスの最初の列とクエリメモリアドレスを比較して、メモリアドレスが存在するかどうかを判断します。
これを拡張するために、ここではハッシュテーブルと同様の方法が使用されます。アドレス%10は、実際には単純なハッシュ関数を構成します。
6.指示の先読み
CPUはメモリ内の命令を順番に実行し、CPUは命令を非常に高速に実行します。通常は2〜6 CPUクロックサイクルです。このレッスンでは、メモリのグレーディング戦略を学び、メモリの読み取りと書き込みの速度が実際には非常に速いことを発見しました。遅い、約200〜300クロックサイクルあります。
見つけたのかな?これも非常に厄介な問題を引き起こします。CPUは実際にはメモリから命令を読み取って1つずつ実行することができません。これを行うと、各命令が実行されるまでに200〜300クロックサイクルかかります。
では、この問題にどのように対処するのでしょうか?
ここでもう1つ言いたいことがあります。実際、ビジネス開発RPC呼び出しを行っていると、このような状況に遭遇することがよくあります。リモート呼び出しは全体的な実行効率を低下させます。このタイプの問題の解決策について一緒に話し合いましょう。
1つの解決策は、CPUがメモリ内の数十または数百の命令をL1-キャッシュにプリリードすることです。L1-キャッシュの読み取りおよび書き込み速度は高速です。L1-キャッシュの読み取りおよび書き込み速度は2〜4クロックしかないためです。サイクル、それは従うことができます上位CPUの実行速度。
別の問題が発生します。データと命令がL1キャッシュに格納されている場合、データキャッシュが命令キャッシュをカバーしていると、非常に深刻な結果を招きます。したがって、L1キャッシュは通常、2つの領域に分割されます。1つは命令領域で、もう1つはデータ領域です。
同時に、別の問題が発生します。L1キャッシュは命令領域とデータ領域に分割されます。L2/ L3はこのように分割する必要がありますか?実際には必要ありません。L2とL3のため、命令の先読みの問題に対処するのを支援する必要はありません。
7.キャッシュヒット率
次に、解決すべき重要な問題があります。L1 / L2 / L3を合計するだけですが、キャッシュのヒット率はどれくらいですか?
いわゆるヒットとは、キャッシュ内で必要なデータを見つけることを指します。ヒットの反対は侵入であり、ミスとも呼ばれます。これは、読み取り操作がキャッシュから対応するデータを見つけられないことを意味します。
統計によると、L1キャッシュのヒット率は約80%、L1 / L2 / L3の合計ヒット率は約95%です。したがって、CPUキャッシュの設計は非常に合理的です。メモリ読み取りの5%のみがメモリに浸透し、95%はキャッシュに読み取ることができます。これが、プログラミング言語がプログラマーがレジスターを操作できる構文を徐々にキャンセルする理由です。キャッシュは高いヒット率を保証し、冗長な最適化はほとんど重要ではなく、間違いを犯しやすいためです。
8.キャッシュ置換の問題
たとえば、最後の質問では、L1-キャッシュエントリがいっぱいになり、CPUがメモリを再度読み取り、新しいエントリをL1-キャッシュに格納する必要があります。新しいエントリが入力されるため、そこに古いエントリが出ています。したがって、現時点では、アルゴリズムを使用して、どのアイテムを置き換える必要があるかを計算する必要があります。この問題は、キャッシュ置換問題と呼ばれます。キャッシュ置換の問題については、「21 |プロセススケジューリング:プロセススケジューリングの方法は何ですか?」で説明します。
9.まとめ
このレッスンでは、メモリ階層化戦略について説明し、L1 / L2 / L3キャッシュの動作原理について説明しました。このクラスで学習したコンテンツは、すべてのキャッシュ知識のソースです。すべてのキャッシングシステムの設計は、ストレージリソースの階層です。キャッシュを設計するときは、アーキテクチャ全体に加えて、次のような詳細にも注意を払う必要があります。
エントリをデザインする方法は?
アルゴリズムを設計する方法は?
ヒット率はどのようにカウントされますか?
キャッシュ等の交換方法は?
それでは、クラスを終了する前に提起された質問について話しましょう。SSD、メモリ、L1キャッシュの速度の違いは何倍ですか。
【分析】メモリはSSDの10〜1000倍高速であるため、L1キャッシュはメモリの約100倍高速です。したがって、L1キャッシュはSSDよりも1000〜100000倍高速です。SSDには大きな可能性があることがわかりましたか?優れたSSDはメモリに近いですが、コストはわずかに高くなります。
この問題は、異なるメモリ間に大きなパフォーマンスギャップがあることを示しており、メモリ階層を構築することは理にかなっています。階層の目的は、キャッシュシステムを構築することです。
10.面接の質問
Q:合計1Mエントリの2次元配列があるとします。この2次元配列をトラバースする場合、行ごとにトラバースする必要がありますか、それとも列ごとにトラバースする必要がありますか?
A:2次元配列の本質は依然として1次元配列です。これは単なる下付き文字の計算です。たとえば、N行とM列の配列の場合、y番目の行とx番目の列の座標はx + y * Mです。したがって、行座標が増加すると、メモリスペースがジャンプします。列座標が増加すると、メモリ空間は連続します。
CPUが2次元配列をトラバースすると、最初にCPUキャッシュからデータがフェッチされます。
重要な要素は、現在のCPU設計では、一度に1つのメモリアドレスを読み取るのではなく、一度に複数の隣接するメモリアドレスを読み取ることです(メモリ速度200〜300 CPUサイクル、先読みにより効率が向上します)。つまり、これは機械と人との間の合意に相当します。プログラマーがこの合意に従わないと、先読みを利用できなくなります。
一方、読み取りメモリアドレスが大きくジャンプすると、メモリのページ置換がトリガーされます。
さらに、行ごとに2次元データをトラバースすることも、プログラムの局所性の原則に準拠しています。
練習用の質問:
ステップ長1の参照モードで3桁の配列をスキャンするようにループ順序を変更する方法。
回答:右端のインデックスが最も速く変化するように、ループの順序を変更してください。
たとえば、100 200 300 ...の代わりに001002 003 ...前者は、命令の先読みの原則に準拠しているため、後者よりも局所性が優れています。つまり、先読みは、の局所性とも呼ばれます。命令フェッチ。