Mae向きなブログ

Mae向きな情報発信を続けていきたいと思います。

メモリ階層を意識したソフトウェアの作成

現在,『Write Great Code〈Vol.1〉ハードウェアを知り、ソフトウェアを書く』を読んでいます。全部で12章構成ですが,何ヶ月もかけて,やっと,第11章の「メモリのアーキテクチャの構成」まで読み進めてきました。

「11.8 メモリ階層を意識したソフトウェアの作成」の中に,

悪い設計の代表例が,整数値の2次元配列を初期化する次のようなループです。
  (途中略)
信じられないような話ですが,現在のCPUでは,このコードの実行速度は次のコードと比べてはるかに劣ります。

とあります。両者(以下,サンプル参照)を見ると,効率が良い/悪いのは分かるのですが,さすがに"はるかに"と書かれていると試してみたくなりました。

以下がサンプルです。良い例と悪い例の違いは,array[i][j] か array[j][i] の違いだけです。

#include <stdio.h>
#ifndef SIZE
#  define SIZE 256
#endif

int main(void)
{
  int array[SIZE][SIZE];
  int i, j;
  for (i = 0; i < SIZE; i++) {
    for (j = 0; j < SIZE; j++) {
#ifdef GOOD
      array[i][j] = i * j;      /* 良い例 */
#else
      array[j][i] = i * j;      /* 悪い例 */
#endif 
    }
  }
  return 0;
}

実験

環境は,

です。

コンパイル

$ gcc memory.c -o good_case -DSIZE=1024 -DGOOD
$ gcc memory.c -o bad_case -DSIZE=1024

bench.rb
require 'benchmark'

Benchmark.bm(7) do |x|
  x.report("good_case:") { system('./good_case') }
  x.report("bad_base :") { system('./bad_case') }
end
計測してみます。

$ ruby bench.rb
user system total real
good_case: 0.000000 0.000000 0.000000 ( 0.013505)
bad_base : 0.000000 0.000000 0.060000 ( 0.059739)

計測結果を見ると,4.4倍くらいの速度の差が見られました。

本書について

まだ読み終わっていませんが,少し感想を書いておきます。

この本を読み進めてきて良かったと思うことは,今まで自分の知識が体系化されず,点として散らばっていた感じだったのが,本書を読むことによって,線で結ばれ体系化されつつあると感じることです。
もっと若い時期に本書に出会っていたら,と思ってしまいます。
もっとも面白いと感じたのは,「第10章 命令セットアーキテクチャ」でしょうか。"Y86仮想プロセッサ"という仮想的なプロセッサに,命令セット設計をしていく過程が興味深いものでした。