
【メモリの場所を意識せよ】効率的なソフトウェアのためのポイント3選
30年以上プログラミングをしているムンペイです。プログラムの効率を最大限に引き出すには、メモリの効果的な管理が欠かせません。
今回は、メモリ管理のポイントを3つ紹介します。
1.メモリの物理的配置を意識する
日頃のプログラミングで、プログラム中のデータがどこに記憶されているかということを意識することはほとんどありませんが、ひとつひとつの変数、配列、文字列、読み込んだファイル、etc.などはコンピュータの中のどこかに書き込まれているはずです。
メモリの場所を意識しなくていいのは、Windows、macOS、LinuxなどのモダンなOSの仮想メモリ機能と、Pythonなどの便利なプログラミング言語のおかげです。
しかし、考えてみれば必ずどこかのメモリに記憶されているに違いありません。
そして、実際の具体的な場所はCPUの中のレジスタまたはキャッシュメモリ、あるいはDDR5-DRAMなどのメインメモリです。
人間の記憶で例えると、レジスタとキャッシュメモリは短期記憶、メインメモリは長期記憶です。短期記憶は、読み書きが速いが、容量がとても少ない。長期記憶は、容量が多いが、読み書きは比較的遅い。
私の場合、プログラミングのときには、自分が使っているデータが、その容量や使い道からしてどこに置かれているか想像しています。
2.メモリごとの速度の違いを知る
データ読み書き速度が、レジスタ、キャッシュメモリ、メインメモリで異なるのは、回路が違うためです。レジスタは電力をガンガン使うが超高速で回路面積も大きい、メインメモリは高密度実装ができて省電力です。
そして、この順にCPUの計算回路の近くに配置します。できるだけ近いメモリを使い、遠いメモリとやり取りする機会を減らすことで、全体を劇的に高速化することができます。
細かい時間はさておき、私は読み書き時間の違いをすごくザックリとイメージしてプログラミングします。具体的にはデータを取り出すのにかかる時間(レイテンシ)をレジスタが1とすると、キャッシュメモリが10、メインメモリが100、ついでに、ストレージ(SSD)がその100倍、ネットワークがその
100倍、位のオーダーです(※4)。
この想定の場合、100個のデータの読み出しをメインメモリから行う場合、
100✕100=10,000
の時間がかかります。
データの50%をキャッシュメモリに置くことができた場合、全体の実行時間は
50✕100+50✕10=5,500
と、約半分になります。
プログラム実行中の多くの時間をキャッシュ上の作業にすることで、全体の速度を大きく向上させることができるでしょう。
※4: こちらの記事に実際の数値がとてもわかりやすくまとめられています。ストレージとネットワークはもっと遅いと認識を改めました https://qiita.com/tarosaiba/items/4a7389d4626c5fb1eba1
3.局所性を作る
キャッシュメモリの活用が効果的であると書きましたが、プログラマーが明示的にキャッシュに置くように指示することは(通常は)できず、CPUとOSが協力して行います。
キャッシュは短期記憶だとも書きましたが、より正確には、最近読み書きしたより遅いメモリアクセスを、短期記憶でサポートして高速化する仕組みなのです。
つまり「最近読み書きした」メモリに何度もアクセスする場合に効果的です。最近読み書きした範囲がキャッシュメモリの容量よりも小さければ、原理的には全ての演算をキャッシュメモリで行うことができます。(し、実際にそれを目指します。)
このような特性を、局所性と言います。
たとえば、2次元的なデータ構造を扱っているとします。たいていのプログラミング言語なら、内側の次元のデータを連続したメモリに配置します。
ですから、計算はなるべく内側の次元に連続してアクセスするのがよいでしょう。
よくないのは、2次元構造全体を縦横無尽にアクセスするような場合です。このような場合は、データ構造を見直して、例えば外側の次元と内側の次元を入れ替えるとメモリ連続にならないか、と言ったことを考えます。
それで解決しないほどバラバラな場合は、ハッシュなどのデータ構造を取りましょう。ハッシュはソフトウェア的なキャッシュです。
局所性は、メモリアクセスだけでなく、ディスクアクセス、ネットワークアクセスなどでも応用できる考え方です。
今どきのコンピュータは高速だから効率化は必要ない?
このように、メモリ管理を意識することで、あなたのプログラムは格段に効率化できます。次にプログラミングをする際には、ぜひこれらのポイントを実践し、プログラムの性能を最大限に引き出してみてください。
今どきのコンピュータは高速だからこんなこと気にしなくていいよねという意見もありそうです。
しかし、効率的なプログラムにできるなら絶対そのほうが良いです。
たしかに、コンピュータでやることが多くなり、まずロジックの実装が優先されて、局所性などに気を遣っている暇がないのはそうかもしれません。
しかし、コンピュータを変えなくても、ソフトウェアが効率的になるだけで性能が簡単に2倍、3倍と変わる可能性があるのです。
これだけ、大量のSEやソフトウェア開発起業が開発しているのですから、世の中には優先度の問題で効率化されていないソフトウェアが大半だろうと想像します。
それらを効率化するだけで、発電所何個分の電力が(もちろん費用も)削減できるかもしれません。それなら、高速化したほうが良いと思いませんか?おっと話が広がり過ぎてきましたので、この話はまたの機会に。。。
これにて御免!
いいなと思ったら応援しよう!
