CPU はメモリをどのように利用するか
2019 年 6 月 12 日 Emil Hozan 著
データをロードしています。お待ちください… CPU がこんなことを言うことはありません(少なくともそう考えたいところですが、現実にはよくあることです)。
開発の初期段階と比べると、テクノロジが短期間で驚くほどの進化を遂げるようになりました。少し前までは、新しい概念が生まれたり、それが発展したりするのに数か月から数年かかることもありましたが、それと比べると、最近の進歩のペースは驚異的であり、1 年半ごとに新しい技術的進歩が発表されるように感じます。記憶容量がわずか 1.44MB だったフロッピーディスクの時代から始まって、最大 20GB の容量のハードディスクへと爆発的な進化を遂げ(この容量も時代と共に増加しています)、最近では、数 TB の SSD であっても、かなり安価で手に入るようになりました。
今回、このブログ記事では、今日のコンピュータソフトウェアアプリケーションがアクセスできる、メインメモリの大きさについて解説します。256MB のダイナミックランダムアクセスメモリ(DRAM)モジュールは、かつては現実不可能とさえ考えられていましたが、最近では、一般的なゲーム用コンピュータが 16GB 以上の DRAM が搭載されるようになりました。
高速処理とメモリの関係
我々が古くから慣れ親しんできた中央処理装置(CPU)は、言うなればコンピュータの心臓部です。詳しい仕組みについては、「コンピュータのチップセットを理解する」という記事で解説しましたが、簡単に言えば、コンピュータの内側では、PC ユーザが目にすることはない、さまざまな処理が実行されています。それらの処理を最終的に統括するのが CPU であり、さまざまなタスクを大勢の「部下」の一人に割り当てます。
CPU は現在、常に先を見越して、かなりの高速で処理を実行します。減速したり遅延したりすることなく動作することを好み、おそらく、データの取得や処理を待つ間であっても、アイドルタイムなど決して発生させないと考えているかのようです。
そこで今回は、以前の「CPU はメモリをどのように利用するか」の内容を発展させ、メモリのピラミッド構造を分解し、いくつかのタイプのメモリの違いを説明し、異なるレベルがどのように連携することで CPU の最大限の有効活用を可能にして超高速パフォーマンスを実現するのかを説明したいと思います。メモリ階層の全体像を理解するには、以下の Wikipedia の図が参考になるでしょう。
図 1:コンピュータのメモリ階層 – 出典:https://en.wikipedia.org/wiki/Memory_hierarchy
メモリの異なるレベルとその用途
メモリには、主として次の 4 つのレベルがあります。
- 内部メモリ
これはプロセッサレジスタとキャッシュです。 - DRAM と呼ばれるメインメモリ
これは速度と容量の異なる RAM モジュールで構成されます。 - 補助メモリ
二次記憶装置とも呼ばれ、機械式ドライブまたはその他の長期記憶装置のメディアで構成されます。そして最後は - オフラインの記憶装置
これについてはこの記事では説明を省略します。
最初の 2 つは揮発性メモリと呼ばれ、電源を切ると保存されていたデータは失われます。これに対して、後者の 2つは不揮発性メモリと呼ばれ、電源を切った後もデータが永続的に保存されます。
CPU は、自らが必要とする時に必要とするものにアクセスすることだけに集中し、それが終われば、次のタスクへと進み、これには高速が必要とされます。RAM は、二次記憶装置と比べると比較的高速のアクセス時間を提供します。メモリバンクが CPU に近いほど、一般的には高速になります。ここで指摘しておかなければならない非常に重要な点の 1 つは、RAM と CPU の間に、CPU レジスタと CPU キャッシュという 2 つのレベルのメモリが存在するということです。
メモリの各レベルの定格速度については、こちらの Wikipedia のリンクを参照してください。
二次記憶装置
今回の説明では、二次記憶装置から始め、逆戻りする形で、次にメインメモリ、最後に内部記憶装置の順に説明します。CPU に近いほど説明が複雑になるので、この順番で説明する方が分かりやすいためです。
最近のコンピュータシステムでは解消されつつありますが、以前は、利用可能なコンピュータメモリ、特に利用可能なメインメモリに問題がありました。当時のメインメモリの容量は今ほど大きくなく、私の初めてのハードウェアのバッチテストでは、RAM モジュールのメモリが 256MB しかありませんでした。コンピュータが RAM の容量より多くのメモリを必要とする場合、ハードディスクの特定のセクタをスワップ領域として利用するか、メインメモリの容量を大きくします。
CPU は、メインメモリに格納されている使用頻度の低いデータを自動的にスワップ領域にオフセットします。そうすることで、高速の RAM を解放して他のアプリケーションが使えるようにしますが、通常はユーザがこの処理を意識することはありません。CPU によるこのデータのオフセットの方法、仮想メモリ(RAM とスワップ領域の組み合わせ)アドレス空間の最初の段階での割り当ての方法、セキュリティに関するその他の考慮事項(ASLR)についても説明が必要ですが、かなり長くなるため、別の記事で解説する予定です。
スワップ領域での処理ではレイテンシが長くなるため、その使用は望ましくなく、今もこの問題が発生するようであれば、解決策を検討する必要があるでしょう。RAM を節約しながら使用する特段の理由はなく、RAM を利用すれば、CPU のサイクルで要求されたプログラム命令を効率的に実行できます。コンピュータの内部の速度が他のテクノロジと同様に進化したため、一般的なユーザにとっては、このレイテンシが問題になることはおそらくありませんが、コンピュータのタスクマネージャ(Windows OS の場合)で RAM の使用率を確認できます。「動作が遅い」時間帯にタスクマネージャを実行し、RAM の使用率が 100% 近いことがわかった場合は、おそらく、RAM の容量を増やす必要があるでしょう。反対に、RAM の使用率は低いものの、CPU の使用率が急上昇している場合、そのアプリケーションが CPU がスムーズに動作しない可能性があります。
メインメモリ、DRAM、SRAM
メインメモリの説明に入る前に、RAM にも関係のある、ある特性について説明しておきたいと思います。メインメモリは一般的に DRAM で構成されますが、静的 RAM(SRAM)も存在し、これは主としてプロセッサキャッシュで使用されるもので、詳細については次のセクションで説明します。
DRAM は、メインメモリをアップグレードする場合に購入する、最も一般的な形の RAM であり、格納されているコンテンツを定期的に更新する必要があることから、「動的」と呼ばれています。つまり、ここに格納されているデータは少しずつなくなるため、数ミリ秒ごとに再読み込みする必要があります。結果として速度が遅くなるため、キャッシュメモリとしての使用には適していません。その対極にあるのが、SRAM であり、すでにお気付きかもしれませんが、SRAM はこの再読み込みを必要としないため、処理は高速になりますが、コストは高くなります。電力使用を抑える必要がある、プロセッサキャシュ以外の SRAM の用途としては、モバイルデバイスなどがあります。
SRAM は CPU に近い場所で利用できる、いくつかの異なる層のキャッシュであり、電力を考慮する必要がある用途で使用され、高速ですが、一般的にアップグレードすることはできません。DRAM は、別途購入し、アップグレードすることで、容量を増やすことができるもので、最も一般的な形のメインメモリです。
RAM が大きいほど、アプリケーションの効率的な同時実行が可能になります。もちろん、CPU の処理能力が高いのは良いことですが、メインメモリの大きさがボトルネックの原因になることはよくあります。CPU は、プログラムを開始すると、二次記憶装置からメインメモリ(DRAM)にデータを取り込むことで、CPU との間のアクセスを高速化します。ここには、使用中のアプリケーションが格納され、アプリケーションに対応するすべてのものがクローズすると、永続データがディスクに戻され、CPU はそのアプリケーションに割り当てられていた仮想メモリを解放します。
ここでの速度の決定要素はさまざまであり、RAM モジュールのレイテンシやバスの速度などの多くの要素が関係します。用途によって一定の速度が要求される場合は、これらの要素を理解することが重要です。しかしながら、本題から外れてしまうため、この件については、参考資料でご紹介している最初のブログを参照してください。
内部メモリ、CPU レジスタ、CPU キャッシュレベル
最後に、内部メモリについて説明します。これは、CPU で利用できるオンボードメモリの場所、つまり、プロセッサキャッシュとレジスタのことです。すべての CPU にオンボードキャッシュがあるわけではありませんが、一般的には、レイヤ 1 とレイヤ 2 キャッシュは CPU チップ本体に組み込まれています。キャッシュの方が CPU から遠い場所にあるため、最初にキャッシュ、次にレジスタの順に説明します。
最初にお断りしておくと、これら 2 つの説明はかなり技術的なものになる可能性があります。そこで、できるだけ分かりやすくするよう心掛けつつ、少なくともその目的が何であるかを理解できるように説明したいと思います。
CPU キャッシュ
キャッシュはメインメモリによく似ていますが、容量ははるかに小さく、速度ははるかに高速です。これは、最も一般的に使用される機能とデータのプールあるいはバッファゾーンと考えることができるでしょう。メインメモリから連続してデータを取り出したり、メインメモリにデータを書き込んだりすると時間がかかりますが、キャッシュであればアクセスが高速になります。これは前述のように、CPU に近いほど高速になるためです。
CPU モードによって異なりますが、CPU キャッシュで利用できる用途は他にもあります。たとえば、投機的実行がありますが、ここにも脆弱性が存在する可能性があります。その 1 つである Foreshadow は、攻撃者が悪用することで、メモリで本来なら禁止されているはずの部分にアクセスすることができるという、Intel に固有の脆弱性です。簡単に言えば、投機的実行とは、アプリケーションプロセスが次に何を実行するかを CPU が予測するものであり、この「推測」が正しければ、CPU がクロックサイクルを節約できますが、正しくないと、すべてを元に戻すことになりますが、一部の情報が残されることになり、これらの残された情報が脆弱性の原因となります。
キャッシュにも、いくつかの異なるレベルがあります。最も一般的な CPU は、階層 1 キャッシュと階層 2 キャッシュを提供します。階層 3 を提供するものもありますが、あまり一般的ではありません。階層 4 キャッシュの場合はさらに少なくなります。階層ごとに定格速度が異なります(上記の Wikipedia の Web ページを参照してください)。
最後に、プロセッサレジスタについて説明します。
レジスタは通常、容量は小さく、CPU アーキテクチャに対応しますが、超高速を提供します。今日の CPU のほとんどは 64 ビットですが、これは、レジスタの大きさです。また、プロセッサアーキテクチャによって異なりますが、現在は、1 つだけではなく、複数のレジスタが存在します。これは、命令セットアーキテクチャ(ISA)とも呼ばれます。
レジスタと他の形のメモリとの大きな相違点の 1 つは、レジスタは CPU が実際に格納された値に対してロジックを実行するところであるのに対し、他の形のメモリは単にこれらの値を格納するだけであるという点です。レジスタの例としては、メモリデータレジスタや、すぐに使用するデータを格納しておく中間レジスタなどがあります。もう 1 つはメモリアドレスレジスタで、CPU が次にアクセスしようとしている仮想メモリ内の位置のアドレスを保持します。
この記事の調査を進める過程で、レジスタだけでも 1 つの記事にする価値があることがわかりました。そのため、レジスタについても、別の機会に解説記事をお届けする予定です。
まとめ
この記事の目的は、メモリのコンピュータ内部での動作の仕組みについて解説することです。スタックオーバーフローやバッファオーバーフローなどの、メモリの脆弱性を耳にすることがよくあります。私の記事の最終的な目的は、それらについて解説し、対策について説明することですが、その背景にある基本的なコンピュータの仕組みを理解しておくことで、理解が深まるはずです。
当然ながら、注意しなければならないことはたくさんあります。たとえば、その 1 つである ISA は、処理内容を保存するための CPU のレジスタを指定するものです。この記事で説明したように、CPU キャッシュが攻撃対象となり、CPU に関連する脆弱性につながる可能性もありますが、ISA の要素の構成が異なる場合は、攻撃方法にどのように影響するのでしょうか。この分野にもさまざまな攻撃方法があるはずであり、それを明らかにするには、多くの調査と時間が必要になるでしょう。
参考資料
homepage.cs.uri.edu の寄稿者による、「How Computers Work: The CPU and Memory(コンピュータの仕組み:CPU とメモリ)」、出典:https://homepage.cs.uri.edu/faculty/wolfe/book/Readings/Reading04.htm
Fairhead, H 著(2018 年 8 月 3 日)、「How Memory Works(メモリの仕組み)」、出典:https://www.i-programmer.info/babbages-bag/359-memory-2.html
Tyson, J 著(2000 年 8 月 23 日)、「How Computer Memory Works(コンピュータメモリの仕組み)」、出典:https://computer.howstuffworks.com/computer-memory.htm
Wikipedia の寄稿者による(2018 年 12 月 5 日)、「Memory hierarchy(メモリ階層)」、出典:https://en.wikipedia.org/wiki/Memory_hierarchy
Wikipedia の寄稿者による(2019 年 3 月 11 日)、「Computer memory(コンピュータメモリ)」、出典:https://en.wikipedia.org/wiki/Computer_memory
Woodford, C. 著(2018 年 9 月 24 日)、「Computer Memory(コンピュータメモリ)」、出典:https://www.explainthatstuff.com/how-computer-memory-works.html