Slide 1

Slide 1 text

メモリのおはなし @ottan

Slide 2

Slide 2 text

記憶デバイスの階層構造 ● 記憶デバイスは階層構造 ● 1階層さがるたびに1桁遅くなる ● できるだけ上で済ませたほうがは やい ● クラウドだとディスクに見えてもネッ トワークの先だったり… 1ns〜 5ns〜 100ns〜 1ms〜 10ms〜 10ns〜 イラスト ©ちぇす https://commons.wikimedia.org/wiki/File:Memory_hierarchy.svg

Slide 3

Slide 3 text

メモリのスループットとレイテンシ(帯域と遅延) ● メモリの帯域は土管の太さ、遅延は流れる水の流速 ● 現代のメモリの土管はものすごく太くなったけど 流れの速さはあんまり変わってない… ● 小さなサイズで逐次アクセスすると死亡… イラスト ©いらすとや FSBのイメージ QPI/HTのイメージ

Slide 4

Slide 4 text

スループットで差がつく例 ● Goによる行列ベクトル積のデモ https://gist.github.com/ottan/b6eab7f00511f886eebef8e675e14715 ● キャッシュにはおさまらないデータサイズ 20480*20480*8 / (1024*1024*1024) = 3.125 GB ● ループを入れ替えただけで遅くなる! −50%!

Slide 5

Slide 5 text

行列ベクトル積のメモリアクセス パターン i-j ループ a b j-i ループ a b ● iとjを交換するとループが行方向から列方向に変化 ● 列方向だとメモリ上のアクセスパターンが飛び飛びになる!

Slide 6

Slide 6 text

メモリの帯域をつかいこなす ● 必要になる前からメモリを先読みして余った帯域を有効活用! ● ソフトウェア プリフェッチ メモリから持ってくるデータを専用の命令で指定して取得 ● ハードウェア プリフェッチ CPU がメモリへのアクセス傾向を判断して自動で取得 ただし、メモリ上で連続したアクセスをする必要がある 複数のストリームもサポート x86 も arm も最近のアーキテクチャだとだいたいある

Slide 7

Slide 7 text

padding 時のプリフェッチの動作 ● 無駄に要素にパッド入れた構造体に変えたデモ https://gist.github.com/ottan/9b3ce7593c8dad18b44a11ea182f091c ● float64 の 8 byte からパッド入れた構造体 16 byte に ● ストライドがキャッシュのラインサイズ以下なら先読みしてくれるっぽい?

Slide 8

Slide 8 text

CPU 追補 ● 最近の CPU はそれぞれのコア群の下にメモリを配置したりする 1 CPU なのに 分散メモリ! (NUMA) ● mysql あたりだと、ちゃんと NUMA に対応できてないので、 処理を行うコアの近くのメモリを使うような仕組みにはなってない… ● NUMA にちゃんと対応するにはミドルウェアから頑張らないと… ● Go は? NUMA-aware scheduler for Go https://docs.google.com/document/u/0/d/1d3iI2QWURgDIsSR6G2275vMeQ_X7w-qxM2Vp7iGwwuM/pub https://news.ycombinator.com/item?id=12459508 MEM NODE

Slide 9

Slide 9 text

参考文献 ● Intel® 64 and IA-32 Architectures Optimization Reference Manual https://software.intel.com/sites/default/files/managed/9e/bc/64-ia-32-architectures-optimization-manual.pdf ● インテル® 64 および IA-32 アーキテクチャー 最適化リファレンス・マニュアル参考訳 https://www.isus.jp/wp-content/uploads/pdf/64-ia-32-architectures-optimization-manual-April2018-040JA.pdf