メモリアクセスの高速化
通常のメモリアクセス
- OSECPUではたった一度のメモリアクセスに際して、これだけのメモリアクセスが必要になる。
- ポインタは上限より小さいか。[1]
- ポインタは下限より大きいか。[1]
- アクセスしたい領域はまだfreeされていないかどうかのシグネチャチェック。[3]
- 実際のアクセス。[1]
- これはポインタレジスタがP02やP03などの実レジスタだった場合の話で、P05とかだったらポインタをロードするためのメモリアクセスもある。
- ここではmemo0002の2013.04.10の(4)の[2]のレベルの場合の話。
- これはひどい。実際のメモリアクセスの6倍ものアクセスが発生してしまっている。これはいかにも遅そうだ。
- そしてあまりにも遅いと[2]のレベルを使う気がしなくなってしまう危険性がある。
アイデア(0)
- ということで、こんなものを考えている。だいぶ前から考えていたんだけど、いくつかの案のうち結局これが一番いいんじゃないかと思う。
- OSECPUに専用のバッファを提供する。これは巨大なベクトルレジスタだと思ってもいい。これは整数レジスタを256本を束ねたものになっている。
- このレジスタは256本をいっせいにメモリに読んだり書いたりすることができる。これに際しても前述のチェックは当然働くけど、それは1回で済むので256回の正味のアクセスに対してオーバーヘッドは5で済む。これなら2%ほどしかオーバヘッドがないことになる。
- バッファも結局はメモリなので、このバッファへのアクセスの分でさらに256回のアクセスが必要になる。
- このバッファは添え字をつけて任意の要素にアクセスすることができる。このとき、このバッファはfreeされないのでシグネチャチェックはないし、添え字に対するチェック機構はメモリアクセスを必要としない。
- 結局、バッファに転送する際に(256*2+5)回のメモリアクセスが発生し、そしてその256本のデータにアクセスする際に256回のメモリアクセスが発生していることになる。だから3.02倍のアクセス量ということになる。これはまだ十分だとはいえないかもしれないけど、とにかく元の6倍よりは2倍も改善している。
- しかもそれでいて安全性に関しては全く妥協していない。
- この方法は256よりも少ない量の「端数」に対しては有効ではない。しかし大きい単位のときに高速化できれば、全体的な性能は十分に上がると思う。
アイデア(1)
- 結局性能が2倍しか上がらないのであれば、普通のアクセスで2個のレジスタにアクセスすればいいんじゃないかという気はする。
- でもそれだと正味2のアクセスに対して(2+5)=7のアクセスが発生するので、3.5倍程度にしか下がってない。
- それではということで、4個のレジスタにしたらどうだろうか。4に対して9のアクセスなので、2.25倍にまで下がる。実際は4個目のレジスタは仮想レジスタになるので、「ストア+あとで実レジスタに持ち替える」コストで11のアクセスになる。そう考えると2.75倍といったところか。
アイデア(2)
- そもそもチェックの量を減らすことはできないかという考え方もある。コード内に制限区域というものを設定する。そして以下の制限がある。
- 制限区域からは制限区域にしか分岐できない。外へ出ることも、外から入ってくることもできない。制限区域の上端から進入して、末端から出ていくことしかできない。中でループすることはできる。
- 制限区域内では、管理下に置く管理下に置くポインタレジスタを複数指定できる。管理下に置かれると、そのポインタに対して、値を代入できなくなる。絶対値の小さな定数を足したり引いたりすることはできる。
考察
- どちらのアイデアがいいかという話だけど、(1)の強みは、自分でFPGAなどでCPUを作りさえすれば、バッファを全部本当にレジスタ化できてしまうというところだ。そうなれば本当に2%のオーバーヘッドだけで安全が得られてしまう。
- (2)の強みは、x64やARMのように実レジスタが多いマシンでは、R00からR03はすべて実レジスタ化されるのが確実なので、2.25倍が実現できるということだ(オーバーヘッド125%)。これは現実的な値だと思う。
- どちらにしても、実際の処理内容はメモリアクセスだけではなく、各種の演算もある。だから体感速度が2%や125%増えるというわけではない。その半分以下だろう。だからそんなに悲観しなくてもいいのかもしれない。
こめんと欄
- このページにこめんと欄はありません。このページの内容にコメントしたいときはimpressionsにお願いします。