細かいチューニングが大切なとき「も」ある話

「痛い」とか言われてムと思ったので、一見バカバカしいチューニングでも決定的な意味があること「も」あるということを書いておこうと思った。

      • -

最近のハードウェアは早くなったといいながら、メモリアクセスは結構遅いというのを、最近どこかで話題になっていたような気がするのですが、
私が今すぐ思い出せるところでは、OCamlの配列のサイズ制限の話題の中で、
http://caml.inria.fr/pub/ml-archives/caml-list/2006/05/6550c9399e4220161a4909a8848a772a.en.html

Doing a memory reference that is satisified out of L1 cache generally takes 1-4 clock cycles. If you have to go to L2 cache, that's going to take 10-40 clock cycles (approximately). Going to main memory? 100-350+ clock cycles. With a large array, you're likely going to take the 100-350+ clock cycle hit anyways. If the top level array is in L1 cache, you're only adding 1-4 clockcycles to the 100-350+ clock cycle hit you're going to take anyways.

というくだりがあって、要は、L1キャッシュにヒットするかメインメモリまでとりに行くかでは、100倍くらいの差が生まれてしまうということがあるのです。
今は、メインメモリはG単位のものまで普通に使われるようになりましたが、キャッシュメモリはL1が数K〜数10KでL2が数10K〜1M程度の非常に小さな容量しかないわけで、この小さな容量を有効活用しようと思ったら、結局のところ地道なチューニングが効いてくるわけなのです。

      • -

今回、私が念頭に置いているのは、Concurrent Cleanの項グラフ書き換え系のノードの部分のデータ構造なので、ものすごく頻繁にオブジェクトの生成・書換・破棄が起こる(それが計算を進めることと同義)ことが分かっているので、100万回アクセスされなければ差が出ないようなところでも、目に見える差にならないとはいえないと思うからこそ、普段なら考えもしないfinal指定による効率の差のようなところまで検討をいれているわけです。

      • -

そういえば、最近話題のJudy Arrayの10分説明を読みましたが、そこでもキャッシュミスが速度に与える影響についての言及がありましたね。
http://judy.sourceforge.net/doc/10minutes.htm