あるキャッシュメモリの話
第一回 カーネル/VM探検隊@名古屋
えとみ なるあき
@nullnilaki
おやくそく
UVMはNetBSDおよびOpenBSDの
メモリ管理システムのことです!
自己紹介
• えとみ なるあき
• 港湾物流業界というニッチな世界で働いています
• 文系です
• 仕事ではCOBOLしか使った事が有りません
A-VXでCOBOLを覚えました
• COBOL結構好き!
自己紹介
コンテナ(仮想)を管理した事がある人は結構いると思いますが、
コンテナ(物理)を管理した事がある人は会場には私だけのはずです!
さて、趣味の話
あるmmapの話
2014年3月9日に開催されたカーネル/VM探検隊@関西6で
Alpha Station DS15にNetBSDを移植した際に
bus_space_mmapのバグを発見し、
PCIバスをもつAlphaマシンでフレームバッファを
正しくマップできない問題を解決したという話をしました
Titanチップセット
Alpha Station DS15(1CPU)
にはTitanチップセットが使われており、
このチップセットは他に
Alpha Station/Server DS25(2CPU)
や
Alpha Server ES45(4CPU)
に使われています
Alpha Server DS25
CPU
Alpha Server DS25 CPU UNIT
MPカーネルは今日も元気です。
つまんねぇ!
AlphaStation DS15とAlpha Station DS25
同じCPU
同じクロック
同じチップセット
違いは
二次キャッシュの
容量!
(2MBと8MB)
姫野ベンチ
dynamic allocate version Grid-size=M
★ DS15とDS25のスコアの差は
キャッシュ容量が原因?
★ cccよりgccのほうがスコアが
良い?
★ Tru64とNetBSDではスコアが
倍以上違う?
NetBSDで性能向上させたい…
ページカラーリング
キャッシュメモリでのスラッシングを防ぐ、
あるいは積極的にキャッシュヒット率を向上させようとする
物理ページ管理手法をページカラーリングと呼ぶ。
ページカラーリングはまた、
仮想インデックスキャッシュのエイリアス問題への回避策
としても使われた。
キャッシュは年々巨大化しているが、
ページサイズは4Kバイトが一般的で
これはページング方式が一般化してから変わっていない。
物理アドレスをインデックスとするキャッシュでは、
物理ページと仮想ページのマッピングによってはキャッシュ上で
現に使用中のページの対応する位置が衝突してしまい、
巨大なキャッシュを生かしきれない事態が発生することがある。
Wikipediaより
実験
/sys/arch/alpha/alpha/dec_6600.c
#include <dev/cons.h>
+#include <uvm/uvm_extern.h>
#include <machine/rpb.h>
+static int external_cache_probe(int minsize, int width);
#ifdef KGDB
#include <machine/db_machdep.h>
@@ -102,6 +115,7 @@
void
dec_6600_init(void)
{
platform.family = "6600";
@@ -115,11 +129,52 @@
platform.device_register = dec_6600_device_register;
platform.mcheck_handler = dec_6600_mcheck_handler;
+
+ uvmexp.ncolors = atop(external_cache_probe(1024*1024, 6));
+
/* enable Cchip and Pchip error interrupts */
STQP(TS_C_DIM0) = 0xe000000000000000;
STQP(TS_C_DIM1) = 0xe000000000000000;
}
external_cache_probeはLinuxのarch/alpha/kernel/setup.cを参考にして下さい
DS15の移植を通して
L2キャッシュが設定されて
無い事は知ってたので
L2キャッシュをプローブして
適切に設定し、効果を実験
実験
Alpha Station DS15
Direct-mapped L2 Cache:2MB
2048K Bcache detected; load hit latency 24 cycles, load miss latency 136
cycles
uvmexp.colors = 256 (2048K / PAGE_SIZE) PAGE_SIZE = 8K
Alpha Server DS25
Direct-mapped L2 Cache:8MB
8192K Bcache detected; load hit latency 24 cycles, load miss latency 138
cycles
uvmexp.ncolors = 1024 (8192K / PAGE_SIZE) PAGE_SIZE = 8K
colorの計算方法 = Cache size/assoc/PAGE_SIZE
L2キャッシュはちゃんとプローブされ、
カラーも設定されています
姫野ベンチ
dynamic allocate version Grid-size=M
page coloringを
設定したら
性能ダダ下がり…
(´;ω;`)ウッ
そもそもキャッシュメモリとは?
キャッシュメモリ (cache memory) は、
CPUなど処理装置がデータや命令などの情報を取得/更新する際に
主記憶装置やバスなどの遅延/低帯域を隠 し、
処理装置と記憶装置の性能差を埋めるために用いる
高速小容量メモリのことである。
略してキャッシュとも呼ぶ。
コンピュータは以前から記憶装置や伝送路の性能が
処理装置の性能に追いつけず、
この差が全体性能に対する
ボトルネックとされてきた(ノイマンズ・ボトルネック)。
そしてムーアの法則に基づく処理装置の加速度的な高性能化により
現在ではますますこの差が拡大されている。
キャッシュメモリは、記憶階層の観点からこれを解消しようとするものである。
Wikipediaより
キャッシュメモリ
VIVTはあんまりない
TLB
VIPTは一次キャッシュ
に一般的に使われる
PIPTは二次キャッシュ
に一般的に使われる
仮想キャッシュ
• プログラムの仮想アドレスを使ってキャッシュをインデックス
する
• メリット
☆ 高速
☆ 仮想アドレスを使ってキャッシュを引くため
アドレス変換を行わずに済み、
CPUにデータを素早く返す事が出来る
• デメリット
★ 容量が少ない
★ 仮想アドレスを使ってキャッシュを引くため
エイリアス、曖昧性、DMA処理等で問題が発生する
したがって適切なメンテナンスが必要
DMAの問題
デバイスがDMA転送を行う場合
キャッシュの中身は考慮されないため、
メインメモリが変更されたり読み出されたりすると
キャッシュとメインメモリとの間の
コヒーレンシが∼(以下略…)
R10K and non-cache-coherent systems
> boot -f pci(0)scsi(0)cdrom(4)rdisk(0)partition(8)ip3xboot
51312+1792 entry: 0x80002000
NetBSD/sgimips 6.1.5 Bootstrap, Revision 1.5
devopen: pci(0)scsi(0)cdrom(4)rdisk(0)partition(0) type scsi file ip3x
9676336+143472=0x95db74
phys segment: 0xd000 @ 0x2000
adding 0xd000 @ 0x2000 to freelist 0
pmap_steal_memory: seg 2: 0x9be 0x9be 0xd50 0xd50
pmap_steal_memory: seg 2: too small for 1176 pages
pmap_steal_memory: seg 3: 0x1400 0x1400 0xfffe 0xfffe
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009, 2010, 2011, 2012
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.
NetBSD 6.1.5 (INSTALL32_IP3x)
total memory = 256 MB
(6848 KB reserved for ARCS)
avail memory = 235 MB
mainbus0 (root): SGI-IP32 [SGI, b], 1 processor
cpu0 at mainbus0: MIPS R12000 CPU (0xe23) Rev. 2.3 with unknown FPC type (0x900) Rev. 0.0
cpu0: 64 TLB entries, 16MB max page size
cpu0: 32KB/64B 2-way set-associative L1 instruction cache
cpu0: 32KB/32B 2-way set-associative write-back L1 data cache
cpu0: 1024KB/64B 2-way set-associative write-back L2 data cache
crime0 at mainbus0 addr 0x14000000: rev 1.4 (CRIME_ID: 17592186044577)
crmfb0 at mainbus0 addr 0x16000000: SGI CRIME Graphics Display Engine
crmfb0: initial resolution 1280x1024
カーネル読み込んで
UVM初期化して
デバイスプローブ
R10K and non-cache-coherent systems
ahc1: aic7880: Ultra Wide Channel A, SCSI Id=0, 16/253 SCBs
scsibus1 at ahc1: 16 targets, 8 luns per target
scsibus0: waiting 2 seconds for devices to settle...
scsibus1: waiting 2 seconds for devices to settle...
ahc0:parity error detected in Data-in phase. SEQADDR(0x7c) SCSIRATE(0x0)
ahc0:parity error detected in Data-in phase. SEQADDR(0x7c) SCSIRATE(0x0)
ahc0:parity error detected in Data-in phase. SEQADDR(0x171) SCSIRATE(0x0)
ahc0:parity error detected in Data-in phase. SEQADDR(0x1c2) SCSIRATE(0x0)
ahc0:Unexpected busfree in Message-out phase
…
SEQADDR == 0x172
sd0 at scsibus0 target 2 lun 0: <011002015, 004016005023-318350031, 02300130> disk fixed
ahc0:Unexpected busfree in Message-out phase
SEQADDR == 0x172
ahc0:Unexpected busfree in Message-out phase
…
>>>>>>>>>>>>>>>>>> Dump Card State Begins <<<<<<<<<<<<<<<<<
ahc0: Dumping Card State in Data-in phase, at SEQADDR 0x7d
Card was paused
ACCUM = 0xf6, SINDEX = 0xb8, DINDEX = 0xa8, ARG_2 = 0x3
HCNT = 0x40 SCBPTR = 0x1
SCSISIGI[0x54] ERROR[0x0] SCSIBUSL[0x0] LASTPHASE[0x40]
SCSISEQ[0x12] SBLKCTL[0x2] SCSIRATE[0x0] SEQCTL[0x10]
SEQ_FLAGS[0x20] SSTAT0[0x0] SSTAT1[0x3] SSTAT2[0x0]
<<<<<<<<<<<<<<<<< Dump Card State Ends >>>>>>>>>>>>>>>>>>
sg[0] - Addr 0xc0fdc50f : Length 128
sd0(ahc0:0:2:0): ahc0: no longer in timeout, status = 0
ahc0: Issued Channel A Bus Reset. 1 SCBs aborted
SCSIをプローブしてから
おや!?O2のようすが…!
R10K and non-cache-coherent systems
エイリアスの問題
物理ページ=0x5e651000
をマップする
2つの仮想アドレス
0x8049000と0xdaf51000
仮想アドレス=0x8049000
にabcdeを書き込んだ時、
ライン0x900は更新されるが
ライン0x100は更新されない
同じ物理アドレスを
マップしているのに
キャッシュ内でデータが不一致
12345
物理キャッシュ
• プログラムの物理アドレスを使ってキャッシュをイン
デックスする
• メリット
☆ エイリアス、曖昧性の問題が発生しない
• デメリット
★ アドレス変換が発生する
(一次キャッシュのアクセスと並行してアドレス変換する)
★ OSのページ割当の方法によっては
キャッシュスラッシングが発生して、性能が出ない
では、NetBSDではどうなっているのか?
ページカラーリング実装
uvm_page_physload()で
vm_physmem構造体に
OSが使える物理メモリの
範囲や優先度を登録
ページカラーリング実装
ページカラーリング実装
ページカラーリング実装
uvm_page_physload()で
vm_physmem構造体に
OSが使える物理メモリ
範囲や優先度を登録したので、
使用出来る総ページ数を割り出す
ページカラーリング実装
例
ページカラーリング実装
バケツの数(カラー)
と
OSが最終的に管理する
ページ数を割り出す
uvmexp.ncolorsが
設定されていなければ
defaultの1を設定
colorの設定方法は色々
recolorするarchもある
uvm_page_init()
ページカラーリング実装
例続き
ページカラーリング実装
pgflbucket構造体のサイズ
カラーの数
2(uvm.page_freeとuvm.cpus[0]->page_free用)
+
割り出したページ数 vm_page構造体のサイズ
メモリを割り当てる
(例だと0x18d2438バイト)
uvm_pageboot_alloc()で
メモリが奪われ、
vm_physseg.start
vm_physseg.avail_startが押し上げられる
例だと0x18d2438バイト -> 0x18d2ページ
vm_physseg.start = 0x1000
↓
vm_physseg.start = 0x28d2
uvm_page_init()
ページカラーリング実装
例続き
ページカラーリング実装
uvm_pagefree()で
空ページ管理リストにvm_page構造体を割り当てていく
uvm_page_init()
vm_page構造体に管理する
物理アドレスをセット
ページカラーリング実装
例続き
ページカラーリング実装
ページカラーリング実装
* o free
* => pageq.list is entry on global free page queue
* => listq.list is entry on per-CPU free page queue
* => uanon is unused (or (void *)0xdeadbeef for DEBUG)
* => uobject is unused (or (void *)0xdeadbeef for DEBUG)
* => PQ_FREE is set in pqflags
uvm.page_free
と
ucpu->page_free
の二つの空きページリストに登録
uvm_pagefree()
ページカラーリング実装
例続き
ページカラーリング実装
例続き
ページカラーリング実装
例続き
ページカラーリング実装
uvm_page_init()
uvm.page_init_doneに
フラグを立てて、おしまい!
たくさんのmalloc()
uvmで匿名ページの割当は
uvmfault_promote()が行っている
uvm_pagealloc()で
vm_page構造体(物理アドレス)
を取得する
uvm_pagealloc()の引数に
ページフォルトした仮想アドレスと
UVM_FLAG_COLORMATCH
がある事に注目
たくさんのmalloc()
uvm_pagealloc()の引数に
UVM_FLAG_COLORMATCH
が指定されている場合は、
ページフォルトした仮想アドレス
と同じ色のカラーを持つ
vm_page構造体(物理ページ)
を割り当てる
指定されていない場合は、
カラーの色は
ラウンドロビン(順番に回る)で
vm_page構造体(物理ページ)
を割り当てる
uvm_pagealloc_start()
は
uvm_pagealloc()のdefine
たくさんのmalloc()
uvm_pagealloc_start()
カラーが決まったので、
uvm_pageallc_pgfl()で指定した
カラーのvm_page構造体を取得する
たくさんのmalloc()
たくさんのmalloc()
カラーはラウンドロビンなので、
1つカラーを進める
条件に有ったvm_page構造体を返す
呼び出した関数でpmap_enter()して
仮想アドレスと物理アドレスの紐付けする
エイリアス問題への対応
エイリアス問題への対応
エイリアス問題への対応
カラーが不一致のばあい、
同じ物理アドレスを
マップしているのに
2つの仮想アドレスで
読み書きをすると
キャッシュ内でデータが不一致
エイリアス問題への対応
カラーが一致するばあい、
キャッシュラインが
競合するので
常にキャッシュミスを起こし、
メモリへの読み書きが
発生するため
データの不一致が発生しない
実際はさらにpmap()で
ゴニョゴニョ
Alpha Station XP1000
XP1000は
@impreza_gf8さんから
譲っていただきました!
この機種はNetBSD1.4の頃から
サポートされている
(二次キャッシュのプローブはなし)
4096K Bcache detected;
load hit latency 20 cycles,
load miss latency 105 cycles
姫野ベンチ
dynamic allocate version Grid-size=M
昔のNetBSD 4を使って、page coloringを行うように変更した場合、
性能向上が見られた!
2回目の実行で顕著に
性能差が見られるのは
1回目の内容がキャッシュに
残っているため?だと思われる
姫野ベンチ
dynamic allocate version Grid-size=M
現在のNetBSD currentを使って、page coloringを行うように変更した場合、
劇的に性能が落ちた!
UVM_FLAG_COLORMATCHが無い!
currentの処理
NetBSD4の頃はcolorの設定はラウンドロビン
NetBSD6以降は、UVM_FLAG_COLORMATCH
で仮想アドレスから
カラーを指定する事も出来る(仮想アドレスキャッシュ対策)
大きいキャッシュに大きいページ、そこそこメモリ
COMPAQ Professional Workstation XP1000,
500MHz, s/n
8192 byte page size, 1 processor.
4096K Bcache detected;
total memory = 512 MB
(2128 KB reserved for PROM, 509 MB used by NetBSD)
avail memory = 492 MB
このばあい、colorは512で
しらべたところ、62831pageを扱っていた。
大きいキャッシュに大きいページ、そこそこメモリ
カラーが多すぎて、
そのカラーのvm_page構造体が
12個しかない…
大きいキャッシュに大きいページ、そこそこメモリ
おそらく,ログインプロンプトが出た時点で
すでにいくつかの空きページリストはNULL
大きいキャッシュに大きいページ、そこそこメモリ
大きいキャッシュに大きいページ、そこそこメモリ
匿名ページ割当関数の
uvmfault_promote()
でのUVM_FLAG_COLORMATCH
を外した所、性能向上が見られました
大きいキャッシュに大きいページ、そこそこメモリ
ここで質問
uvmfault_promote()のUVM_FLAG_COLORMATCH、
取っては駄目なんでしょうか?
どういうタイミングの時に匿名ページの割当でカラーを合わせる必要が有るのか?
いまいち です
ここで質問
DS25の場合、8MB 1024colorという巨大さ
でも、なぜか2回目が遅い?
スラッシングはしてないはずだけれど?なぜ?
参考文献&お世話になった方々
☆ UNIXカーネル内部解析 キャッシュとマルチプロセッサの管理
☆ SOLARIS インターナル カーネル構造の全て
☆ BSDカーネルの設計と実装 FreeBSD詳細
☆ UNIXカーネルの設計
☆ 最前線のUNIXのカーネル
☆ BSD magazine 13号 NetBSDの設計と実装
☆ NetBSD UVM page coloringメモ
  http://togetter.com/li/203520
☆ コンピュータアーキテクチャの話
12 キャッシュの構造や働き(上級編) - メモリエーリアス
  http://news.mynavi.jp/column/architecture/012/
★ つついさんを始め、なまあたたかい目でアドバイスをくださる
NetBSDなかたがた
★ Alpha Station XP1000を譲って下さった、@impreza_gf8様
★ Alpha Station 200を譲って下さった、@syuu1228様
★ ふぁぼってくださる、フォロワーさん

あるキャッシュメモリの話